From ef80d82222d630320026616da5317ede4ba4d5f0 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Mon, 6 Jan 2020 15:02:00 -0800 Subject: [PATCH 001/116] Checkin prototype with small example profile JSON --- .gitignore | 26 + .parcelrc | 6 + .postcssrc | 5 + .prettierignore | 7 + .prettierrc | 4 + index.html | 10 + package.json | 27 + src/App.css | 17 + src/App.js | 763 ++ src/Canvas.js | 30 + src/EventTooltip.css | 64 + src/EventTooltip.js | 216 + src/SelectedEvent.js | 47 + src/SelectedEvent.module.css | 11 + src/canvasUtils.js | 34 + src/constants.js | 57 + src/contexts.js | 4 + src/index.css | 13 + src/index.js | 8 + src/logo.svg | 1 + src/preprocessData.js | 298 + src/preprocessFlamechart.js | 21 + src/serviceWorker.js | 135 + src/speedscope/README.md | 1 + src/speedscope/import/chrome.js | 228 + src/speedscope/import/v8cpuFormatter.js | 39 + src/speedscope/lib/demangle-cpp.js | 32 + src/speedscope/lib/file-format-spec.js | 13 + src/speedscope/lib/flamechart.js | 97 + src/speedscope/lib/math.js | 302 + src/speedscope/lib/profile.js | 514 ++ src/speedscope/lib/utils.js | 254 + src/speedscope/lib/value-formatters.js | 59 + src/tracerbench/trace/bounds.js | 27 + src/tracerbench/trace/cpu-profile.js | 316 + src/tracerbench/trace/index.js | 11 + src/tracerbench/trace/process.js | 26 + src/tracerbench/trace/render-events.js | 138 + src/tracerbench/trace/thread.js | 12 + src/tracerbench/trace/trace.js | 292 + src/tracerbench/trace/trace_event.js | 54 + .../trace/trace_event_comparator.js | 34 + src/types.js | 59 + src/useDebounce.js | 28 + src/useInteractiveEvents.js | 127 + src/usePanAndZoom.js | 296 + src/useSmartTooltip.js | 57 + src/utils.js | 46 + yarn.lock | 6331 +++++++++++++++++ 49 files changed, 11197 insertions(+) create mode 100644 .gitignore create mode 100644 .parcelrc create mode 100644 .postcssrc create mode 100644 .prettierignore create mode 100644 .prettierrc create mode 100644 index.html create mode 100644 package.json create mode 100644 src/App.css create mode 100644 src/App.js create mode 100644 src/Canvas.js create mode 100644 src/EventTooltip.css create mode 100644 src/EventTooltip.js create mode 100644 src/SelectedEvent.js create mode 100644 src/SelectedEvent.module.css create mode 100644 src/canvasUtils.js create mode 100644 src/constants.js create mode 100644 src/contexts.js create mode 100644 src/index.css create mode 100644 src/index.js create mode 100644 src/logo.svg create mode 100644 src/preprocessData.js create mode 100644 src/preprocessFlamechart.js create mode 100644 src/serviceWorker.js create mode 100644 src/speedscope/README.md create mode 100644 src/speedscope/import/chrome.js create mode 100644 src/speedscope/import/v8cpuFormatter.js create mode 100644 src/speedscope/lib/demangle-cpp.js create mode 100644 src/speedscope/lib/file-format-spec.js create mode 100644 src/speedscope/lib/flamechart.js create mode 100644 src/speedscope/lib/math.js create mode 100644 src/speedscope/lib/profile.js create mode 100644 src/speedscope/lib/utils.js create mode 100644 src/speedscope/lib/value-formatters.js create mode 100644 src/tracerbench/trace/bounds.js create mode 100644 src/tracerbench/trace/cpu-profile.js create mode 100644 src/tracerbench/trace/index.js create mode 100644 src/tracerbench/trace/process.js create mode 100644 src/tracerbench/trace/render-events.js create mode 100644 src/tracerbench/trace/thread.js create mode 100644 src/tracerbench/trace/trace.js create mode 100644 src/tracerbench/trace/trace_event.js create mode 100644 src/tracerbench/trace/trace_event_comparator.js create mode 100644 src/types.js create mode 100644 src/useDebounce.js create mode 100644 src/useInteractiveEvents.js create mode 100644 src/usePanAndZoom.js create mode 100644 src/useSmartTooltip.js create mode 100644 src/utils.js create mode 100644 yarn.lock diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000..42bf277f13741 --- /dev/null +++ b/.gitignore @@ -0,0 +1,26 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# production +/build +/dist + +# misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +.parcel-cache/* diff --git a/.parcelrc b/.parcelrc new file mode 100644 index 0000000000000..05f13a17c95e9 --- /dev/null +++ b/.parcelrc @@ -0,0 +1,6 @@ +{ + "extends": "@parcel/config-default", + "transforms": { + "url:*": ["@parcel/transformer-raw"] + } +} \ No newline at end of file diff --git a/.postcssrc b/.postcssrc new file mode 100644 index 0000000000000..d692dc786e552 --- /dev/null +++ b/.postcssrc @@ -0,0 +1,5 @@ +{ + "modules": true, + "plugins": { + } +} \ No newline at end of file diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000000000..08e44b6d41837 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,7 @@ +package-lock.json +yarn.lock +.parcel-cache/* +node_modules/* +static/* +src/speedscope/* +src/tracerbench/* \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000000000..1502887d63fd9 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,4 @@ +{ + "singleQuote": true, + "trailingComma": "es5" +} \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000000000..03f88f1253b23 --- /dev/null +++ b/index.html @@ -0,0 +1,10 @@ + + + + Scheduler profiler POC + + +
+ + + \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000000000..28ae41422d541 --- /dev/null +++ b/package.json @@ -0,0 +1,27 @@ +{ + "name": "scheduling-profiler-prototype", + "version": "0.0.1", + "scripts": { + "build": "parcel build index.html", + "prettier": "prettier --write '**/*.{js,json,css}'", + "start": "parcel index.html" + }, + "author": "Brian Vaughn ", + "license": "MIT", + "dependencies": { + "array-binsearch": "^1.0.1", + "d3-hierarchy": "^1.1.9", + "lodash.clonedeep": "^4.5.0", + "memoize-one": "^5.1.1", + "pretty-ms": "^5.1.0", + "react": "^16.12.0", + "react-dom": "^16.12.0", + "react-virtualized-auto-sizer": "^1.0.2", + "scheduler": "^0.18.0" + }, + "devDependencies": { + "parcel": "2.0.0-alpha.3.2", + "prettier": "^1.19.1", + "postcss-modules": "^1.4.1" + } +} diff --git a/src/App.css b/src/App.css new file mode 100644 index 0000000000000..b5d535517bc90 --- /dev/null +++ b/src/App.css @@ -0,0 +1,17 @@ +.App { + position: absolute; + top: 0.5rem; + bottom: 0.5rem; + left: 0.5rem; + right: 0.5rem; +} + +.Canvas { +} + +.HighlightContainer { + pointer-events: none; + position: absolute; + top: 0; + overflow: hidden; +} diff --git a/src/App.js b/src/App.js new file mode 100644 index 0000000000000..ea9a50e223086 --- /dev/null +++ b/src/App.js @@ -0,0 +1,763 @@ +// @flow + +import React, { + Fragment, + useEffect, + useLayoutEffect, + useRef, + useState, +} from 'react'; +import { unstable_batchedUpdates } from 'react-dom'; +import memoize from 'memoize-one'; +import usePanAndZoom from './usePanAndZoom'; +import { getCanvasContext } from './canvasUtils'; +import { + durationToWidth, + positionToTimestamp, + timestampToPosition, +} from './usePanAndZoom'; +import useInteractiveEvents from './useInteractiveEvents'; +import EventTooltip from './EventTooltip'; +import SelectedEvent from './SelectedEvent'; +import preprocessData from './preprocessData'; +import preprocessFlamechart from './preprocessFlamechart'; +import styles from './App.css'; +import AutoSizer from 'react-virtualized-auto-sizer'; +import { + BAR_SPACER_SIZE, + BAR_HEIGHT, + COLORS, + SECTION_GUTTER_SIZE, + EVENT_SIZE, + INTERVAL_TIMES, + LABEL_SIZE, + LABEL_FONT_SIZE, + MARKER_GUTTER_SIZE, + MARKER_FONT_SIZE, + MAX_INTERVAL_SIZE_PX, + MARKER_TEXT_PADDING, + MARKER_HEIGHT, + MARKER_TICK_HEIGHT, +} from './constants'; + +import JSON_PATH from 'url:../static/small-devtools.json'; + +import type { + FlamechartData, + ReactEvent, + ReactMeasure, + ReactProfilerData, +} from './types'; + +const REACT_PRIORITIES = ['unscheduled', 'high', 'normal', 'low']; + +const ROW_CSS_PIXELS_HEIGHT = 16; +const TEXT_CSS_PIXELS_OFFSET_START = 3; +const TEXT_CSS_PIXELS_OFFSET_TOP = 11; +const FONT_SIZE = 10; +const BORDER_OPACITY = 0.4; + +const REACT_DEVTOOLS_FONT_SIZE = 12; +const REACT_GUTTER_SIZE = 4; +const REACT_EVENT_SIZE = 6; +const REACT_WORK_SIZE = 12; +const REACT_WORK_DEPTH_OFFSET = 3; +const REACT_EVENT_BORDER_SIZE = 1; +const REACT_PRIORITY_BORDER_SIZE = 1; +const REACT_DEVTOOLS_PRIORITY_SIZE = + REACT_GUTTER_SIZE * 3 + + REACT_EVENT_SIZE + + REACT_WORK_SIZE + + REACT_PRIORITY_BORDER_SIZE; +const REACT_DEVTOOLS_CANVAS_HEIGHT = + (REACT_DEVTOOLS_PRIORITY_SIZE + REACT_PRIORITY_BORDER_SIZE) * + REACT_PRIORITIES.length; + +const FLAMECHART_FONT_SIZE = 10; +const FLAMECHART_FRAME_HEIGHT = 16; +const FLAMECHART_TEXT_PADDING = 3; + +const LABEL_FIXED_WIDTH = LABEL_SIZE + REACT_PRIORITY_BORDER_SIZE; +const HEADER_HEIGHT_FIXED = MARKER_HEIGHT + REACT_PRIORITY_BORDER_SIZE; + +// Time mark intervals vary based on the current zoom range and the time it represents. +// In Chrome, these seem to range from 70-140 pixels wide. +// Time wise, they represent intervals of e.g. 1s, 500ms, 200ms, 100ms, 50ms, 20ms. +// Based on zoom, we should determine which amount to actually show. +function getTimeTickInterval(zoomLevel) { + let interval = INTERVAL_TIMES[0]; + for (let i = 0; i < INTERVAL_TIMES.length; i++) { + const currentInteval = INTERVAL_TIMES[i]; + const pixels = currentInteval * zoomLevel; + if (pixels <= MAX_INTERVAL_SIZE_PX) { + interval = currentInteval; + } + } + return interval; +} + +function getHoveredEvent(data, flamechart, state) { + const { canvasMouseX, canvasMouseY, offsetY } = state; + + if (canvasMouseX < LABEL_FIXED_WIDTH || canvasMouseY < HEADER_HEIGHT_FIXED) { + return null; + } + + if (canvasMouseY + offsetY < REACT_DEVTOOLS_CANVAS_HEIGHT) { + if (data != null) { + const priorityIndex = Math.floor( + (canvasMouseY - HEADER_HEIGHT_FIXED + offsetY) / + REACT_DEVTOOLS_PRIORITY_SIZE + ); + if (priorityIndex >= REACT_PRIORITIES.length) { + return null; + } + + const priority = REACT_PRIORITIES[priorityIndex]; + const baseY = + HEADER_HEIGHT_FIXED + + REACT_DEVTOOLS_PRIORITY_SIZE * priorityIndex - + offsetY; + const eventMinY = baseY + REACT_GUTTER_SIZE / 2; + const eventMaxY = eventMinY + REACT_EVENT_SIZE + REACT_GUTTER_SIZE; + const measureMinY = eventMaxY; + const measureMaxY = measureMinY + REACT_WORK_SIZE + REACT_GUTTER_SIZE; + + let events = null, + measures = null; + if (canvasMouseY >= eventMinY && canvasMouseY <= eventMaxY) { + events = data[priority].events; + } else if (canvasMouseY >= measureMinY && canvasMouseY <= measureMaxY) { + measures = data[priority].measures; + } + + if (events !== null) { + for (let index = events.length - 1; index >= 0; index--) { + const event = events[index]; + const { timestamp } = event; + + const eventX = timestampToPosition(timestamp, state); + const startX = eventX - REACT_EVENT_SIZE / 2; + const stopX = eventX + REACT_EVENT_SIZE / 2; + if (canvasMouseX >= startX && canvasMouseX <= stopX) { + return { + event, + flamechartNode: null, + measure: null, + priorityIndex, + data, + }; + } + } + } else if (measures !== null) { + // Because data ranges may overlap, wew ant to find the last intersecting item. + // This will always be the one on "top" (the one the user is hovering over). + for (let index = measures.length - 1; index >= 0; index--) { + const measure = measures[index]; + const { duration, timestamp } = measure; + + const pointerTime = positionToTimestamp(canvasMouseX, state); + + if (pointerTime >= timestamp && pointerTime <= timestamp + duration) { + return { + event: null, + flamechartNode: null, + measure, + priorityIndex, + data, + }; + } + } + } + } + } else { + if (flamechart !== null) { + const layerIndex = Math.floor( + (canvasMouseY + offsetY - HEADER_HEIGHT_FIXED - REACT_DEVTOOLS_CANVAS_HEIGHT) / + FLAMECHART_FRAME_HEIGHT + ); + const layer = flamechart.layers[layerIndex]; + + if (layer != null) { + let startIndex = 0; + let stopIndex = layer.length - 1; + while (startIndex <= stopIndex) { + const currentIndex = Math.floor((startIndex + stopIndex) / 2); + const flamechartNode = layer[currentIndex]; + + const { end, start } = flamechartNode; + + const width = durationToWidth((end - start) / 1000, state); + const x = Math.floor(timestampToPosition(start / 1000, state)); + + if (x <= canvasMouseX && x + width >= canvasMouseX) { + return { + event: null, + flamechartNode, + measure: null, + priorityIndex: null, + data, + }; + } + + if (x > canvasMouseX) { + stopIndex = currentIndex - 1; + } else { + startIndex = currentIndex + 1; + } + } + } + } + } + + return null; +} + +const cachedFlamegraphTextWidths = new Map(); +const trimFlamegraphText = (context, text, width) => { + for (let i = text.length - 1; i >= 0; i--) { + const trimmedText = i === text.length - 1 ? text : text.substr(0, i) + '…'; + + let measuredWidth = cachedFlamegraphTextWidths.get(trimmedText); + if (measuredWidth == null) { + measuredWidth = context.measureText(trimmedText).width; + cachedFlamegraphTextWidths.set(trimmedText, measuredWidth); + } + + if (measuredWidth <= width) { + return trimmedText; + } + } + + return null; +}; + +const renderReact = ({ + canvasWidth, + context, + eventOrMeasure, + priorityIndex, + showGroupHighlight, + showHoverHighlight, + state, +}) => { + const { timestamp, type } = eventOrMeasure; + const { offsetY } = state; + + let fillStyle = null; + let hoveredFillStyle = null; + let groupSelectedFillStyle = null; + let x, y, width; + + switch (type) { + case 'commit': + case 'render-idle': + case 'render': + case 'layout-effects': + case 'passive-effects': + const { depth, duration } = ((eventOrMeasure: any): ReactMeasure); + + // We could change the max to 0 and just skip over rendering anything that small, + // but this has the effect of making the chart look very empty when zoomed out. + // So long as perf is okay- it might be best to err on the side of showing things. + width = durationToWidth(duration, state); + if (width <= 0) { + return; // Too small to render at this zoom level + } + + x = timestampToPosition(timestamp, state); + if (x + width < 0 || canvasWidth < x) { + return; // Not in view + } + + switch (type) { + case 'commit': + fillStyle = COLORS.REACT_COMMIT; + hoveredFillStyle = COLORS.REACT_COMMIT_HOVER; + groupSelectedFillStyle = COLORS.REACT_COMMIT_SELECTED; + break; + case 'render-idle': + // We could render idle time as diagonal hashes. + // This looks nicer when zoomed in, but not so nice when zoomed out. + // color = context.createPattern(getIdlePattern(), 'repeat'); + fillStyle = COLORS.REACT_IDLE; + hoveredFillStyle = COLORS.REACT_IDLE_HOVER; + groupSelectedFillStyle = COLORS.REACT_IDLE_SELECTED; + break; + case 'render': + fillStyle = COLORS.REACT_RENDER; + hoveredFillStyle = COLORS.REACT_RENDER_HOVER; + groupSelectedFillStyle = COLORS.REACT_RENDER_SELECTED; + break; + case 'layout-effects': + fillStyle = COLORS.REACT_LAYOUT_EFFECTS; + hoveredFillStyle = COLORS.REACT_LAYOUT_EFFECTS_HOVER; + groupSelectedFillStyle = COLORS.REACT_LAYOUT_EFFECTS_SELECTED; + break; + case 'passive-effects': + fillStyle = COLORS.REACT_PASSIVE_EFFECTS; + hoveredFillStyle = COLORS.REACT_PASSIVE_EFFECTS_HOVER; + groupSelectedFillStyle = COLORS.REACT_PASSIVE_EFFECTS_SELECTED; + break; + default: + console.warn(`Unexpected type "${type}"`); + break; + } + + y = + HEADER_HEIGHT_FIXED + + (REACT_DEVTOOLS_PRIORITY_SIZE * priorityIndex + + REACT_GUTTER_SIZE + + REACT_EVENT_SIZE + + REACT_GUTTER_SIZE) - + offsetY; + + let height = REACT_WORK_SIZE - REACT_WORK_DEPTH_OFFSET * depth; + + const lineWidth = Math.floor(REACT_EVENT_BORDER_SIZE); + + if (depth > 0) { + context.fillStyle = COLORS.REACT_WORK_BORDER; + context.fillRect( + Math.floor(x), + Math.floor(y), + Math.floor(width), + Math.floor(height) + ); + + height -= lineWidth; + + if (width > lineWidth * 2) { + width -= lineWidth * 2; + x += lineWidth; + } + } + + // $FlowFixMe We know these won't be null + context.fillStyle = showHoverHighlight + ? hoveredFillStyle + : showGroupHighlight + ? groupSelectedFillStyle + : fillStyle; + context.fillRect( + Math.floor(x), + Math.floor(y), + Math.floor(width), + Math.floor(height) + ); + break; + case 'schedule-render': + case 'schedule-state-update': + case 'suspend': + const { isCascading } = ((eventOrMeasure: any): ReactEvent); + + x = timestampToPosition(timestamp, state); + if (x + EVENT_SIZE / 2 < 0 || canvasWidth < x) { + return; // Not in view + } + + switch (type) { + case 'schedule-render': + case 'schedule-state-update': + if (isCascading) { + fillStyle = showHoverHighlight + ? COLORS.REACT_SCHEDULE_CASCADING_HOVER + : COLORS.REACT_SCHEDULE_CASCADING; + } else { + fillStyle = showHoverHighlight + ? COLORS.REACT_SCHEDULE_HOVER + : COLORS.REACT_SCHEDULE; + } + break; + case 'suspend': + fillStyle = showHoverHighlight + ? COLORS.REACT_SUSPEND_HOVER + : COLORS.REACT_SUSPEND; + break; + default: + console.warn(`Unexpected event or measure type "${type}"`); + break; + } + + if (fillStyle !== null) { + const circumference = REACT_EVENT_SIZE; + y = + HEADER_HEIGHT_FIXED + + (REACT_DEVTOOLS_PRIORITY_SIZE * priorityIndex + + REACT_GUTTER_SIZE + + REACT_EVENT_SIZE / 2) - + offsetY; + + context.beginPath(); + context.fillStyle = fillStyle; + context.arc(x, y, circumference / 2, 0, 2 * Math.PI); + context.fill(); + } + break; + default: + console.warn(`Unexpected event or measure type "${type}"`); + break; + } +}; + +// The canvas we're rendering looks a little like the outline below. +// Left labels mark different scheduler REACT_PRIORITIES, +// and top labels mark different times (based on how long the data runs and how zoomed in we are). +// The content in the bottom right area is scrollable, but the top/left labels are fixed. +// +// ┌----------------------------------- +// | t⁰ t¹ t² ... +// ├-------------┬--------------------- +// | unscheduled ┋ +// ├-------------┼--------------------- +// | high ┋ +// ├-------------┼--------------------- +// | normal ┋ +// ├-------------┼--------------------- +// | low ┋ +// ├-------------┼--------------------- +// | ┋ +// | ┋ +// | ┋ +// └-------------┴--------------------- +// +// Because everything we draw on a canvas is drawn on top of what was already there, +// we render the graph in several passes, each pass creating a layer: +// ,──────── +// axis labels → / +// ,──/ +// profiling data → / '─────────── +// ,─ / +// axis marker lines → / '──────────────── +// ,─ / +// background fills → / '───────────────────── +// / +// '────────────────────────── +// +// TODO Passing "state" directly breaks memoization for e.g. mouse moves +const renderCanvas = memoize( + ( + data, + flamechart, + canvas, + canvasWidth, + canvasHeight, + state, + hoveredEvent + ) => { + const { offsetX, offsetY, zoomLevel } = state; + + const context = getCanvasContext(canvas, canvasHeight, canvasWidth, true); + + // Fill the canvas with the background color + context.fillStyle = COLORS.BACKGROUND; + context.fillRect(0, 0, canvasWidth, canvasHeight); + + // Charting data renders within this region of pixels as "scrollable" content. + // Time markers (top) and priority labels (left) are fixed content. + const scrollableCanvasWidth = canvasWidth - LABEL_FIXED_WIDTH; + + let y = 0; + + const interval = getTimeTickInterval(zoomLevel); + const intervalSize = interval * zoomLevel; + const firstIntervalPosition = + 0 - offsetX + Math.floor(offsetX / intervalSize) * intervalSize; + + // Render all charting data (once it's loaded and processed) within the "scrollable" region. + // TODO (windowing) We can avoid rendering all of this if we've scrolled some of it off screen. + if (data != null) { + // Time markers do not scroll off screen; they are always rendered at a fixed vertical position. + y = HEADER_HEIGHT_FIXED - offsetY; + + REACT_PRIORITIES.forEach((priority, priorityIndex) => { + const currentPriority = data[priority]; + currentPriority.events.forEach(event => { + const showHoverHighlight = + hoveredEvent && hoveredEvent.event === event; + renderReact({ + canvasWidth, + context, + eventOrMeasure: event, + showGroupHighlight: false, + showHoverHighlight, + priorityIndex, + state, + }); + }); + currentPriority.measures.forEach(measure => { + const showHoverHighlight = + hoveredEvent && hoveredEvent.measure === measure; + const showGroupHighlight = + hoveredEvent && + hoveredEvent.measure !== null && + hoveredEvent.measure.batchUID === measure.batchUID; + renderReact({ + canvasWidth, + context, + eventOrMeasure: measure, + priorityIndex, + showGroupHighlight, + showHoverHighlight, + state, + }); + }); + + // Draw the hovered and/or selected items on top so they stand out. + // This is helpful if there are multiple (overlapping) items close to each other. + if (hoveredEvent !== null && hoveredEvent.event !== null) { + renderReact({ + canvasWidth, + context, + eventOrMeasure: hoveredEvent.event, + showGroupHighlight: false, + showHoverHighlight: true, + priorityIndex: hoveredEvent.priorityIndex, + state, + }); + } + }); + } + + // Flame graph data renders below the prioritized React data. + // TODO Timestamp alignment is off by a few hundred me from our user timing marks; why? + if (flamechart !== null) { + context.textAlign = 'left'; + context.textBaseline = 'middle'; + context.font = `${FLAMECHART_FONT_SIZE}px sans-serif`; + + for (let i = 0; i < flamechart.layers.length; i++) { + const nodes = flamechart.layers[i]; + + const y = Math.floor( + HEADER_HEIGHT_FIXED + + REACT_DEVTOOLS_CANVAS_HEIGHT + + i * FLAMECHART_FRAME_HEIGHT - + offsetY + ); + if ( + y + FLAMECHART_FRAME_HEIGHT < HEADER_HEIGHT_FIXED || + canvasHeight < y + ) { + continue; // Not in view + } + + for (let j = 0; j < nodes.length; j++) { + const { end, node, start } = nodes[j]; + const { name } = node.frame; + + let showHoverHighlight = + hoveredEvent && hoveredEvent.flamechartNode === nodes[j]; + + const width = durationToWidth((end - start) / 1000, state); + if (width <= 0) { + return; // Too small to render at this zoom level + } + + const x = Math.floor(timestampToPosition(start / 1000, state)); + if (x + width < 0 || canvasWidth < x) { + continue; // Not in view + } + + context.fillStyle = showHoverHighlight + ? COLORS.FLAME_GRAPH_HOVER + : COLORS.FLAME_GRAPH; + + context.fillRect( + x, + y, + Math.floor(width - REACT_PRIORITY_BORDER_SIZE), + Math.floor(FLAMECHART_FRAME_HEIGHT - REACT_PRIORITY_BORDER_SIZE) + ); + + if (width > FLAMECHART_TEXT_PADDING * 2) { + const trimmedName = trimFlamegraphText( + context, + name, + width - FLAMECHART_TEXT_PADDING * 2 + ); + if (trimmedName !== null) { + context.fillStyle = COLORS.PRIORITY_LABEL; + context.fillText( + trimmedName, + x + FLAMECHART_TEXT_PADDING, + y + FLAMECHART_FRAME_HEIGHT / 2 + ); + } + } + } + } + } + + // LEFT: Priority labels + // Priority labels do not scroll off screen; they are always rendered at a fixed horizontal position. + // Render them last, on top of everything else, to account for things scrolled beneath them. + y = HEADER_HEIGHT_FIXED - offsetY; + + REACT_PRIORITIES.forEach((priority, priorityIndex) => { + context.fillStyle = COLORS.PRIORITY_BACKGROUND; + context.fillRect( + 0, + Math.floor(y), + Math.floor(LABEL_FIXED_WIDTH), + REACT_DEVTOOLS_PRIORITY_SIZE + ); + + context.fillStyle = COLORS.PRIORITY_BORDER; + context.fillRect( + 0, + Math.floor(y + REACT_DEVTOOLS_PRIORITY_SIZE), + canvasWidth, + REACT_PRIORITY_BORDER_SIZE + ); + + context.fillStyle = COLORS.PRIORITY_BORDER; + context.fillRect( + Math.floor(LABEL_FIXED_WIDTH) - REACT_PRIORITY_BORDER_SIZE, + Math.floor(y), + REACT_PRIORITY_BORDER_SIZE, + REACT_DEVTOOLS_PRIORITY_SIZE + ); + + context.fillStyle = COLORS.PRIORITY_LABEL; + context.textAlign = 'left'; + context.textBaseline = 'middle'; + context.font = `${REACT_DEVTOOLS_FONT_SIZE}px sans-serif`; + context.fillText(priority, 10, y + REACT_DEVTOOLS_PRIORITY_SIZE / 2); + + y += REACT_DEVTOOLS_PRIORITY_SIZE + REACT_PRIORITY_BORDER_SIZE; + }); + + // TOP: Time markers + // Time markers do not scroll off screen; they are always rendered at a fixed vertical position. + // Render them last, on top of everything else, to account for things scrolled beneath them. + y = 0; + + context.fillStyle = COLORS.BACKGROUND; + context.fillRect(0, 0, canvasWidth, HEADER_HEIGHT_FIXED); + + context.fillStyle = COLORS.PRIORITY_BORDER; + context.fillRect(0, MARKER_HEIGHT, canvasWidth, REACT_PRIORITY_BORDER_SIZE); + + // Draw time marker text on top of the priority groupings + for ( + let i = firstIntervalPosition; + i < scrollableCanvasWidth; + i += intervalSize + ) { + if (i > 0) { + const markerTimestamp = positionToTimestamp( + i + LABEL_FIXED_WIDTH, + state + ); + const markerLabel = Math.round(markerTimestamp); + + const x = LABEL_FIXED_WIDTH + i; + + context.fillStyle = COLORS.PRIORITY_BORDER; + context.fillRect( + x, + MARKER_HEIGHT - MARKER_TICK_HEIGHT, + REACT_PRIORITY_BORDER_SIZE, + MARKER_TICK_HEIGHT + ); + + context.fillStyle = COLORS.TIME_MARKER_LABEL; + context.textAlign = 'right'; + context.textBaseline = 'middle'; + context.font = `${MARKER_FONT_SIZE}px sans-serif`; + context.fillText( + `${markerLabel}ms`, + x - MARKER_TEXT_PADDING, + MARKER_HEIGHT / 2 + ); + } + } + } +); + +function App() { + const [data, setData] = useState(null); + const [flamechart, setFlamechart] = useState(null); + + useEffect(() => { + fetch(JSON_PATH) + .then(data => data.json()) + .then(data => { + // Filter null entries and sort by timestamp. + // I would not expect to have to do either of this, + // but some of the data being passed in requires it. + data = data.filter(Boolean).sort((a, b) => (a.ts > b.ts ? 1 : -1)); + if (data.length > 0) { + unstable_batchedUpdates(() => { + const processedData = preprocessData(data); + setData(processedData); + + const flamechart = preprocessFlamechart(data); + setFlamechart(flamechart); + }); + } + }); + }, []); + + return ( +
+ + {({ height, width }) => ( + + )} + +
+ ); +} + +function AutoSizedCanvas({ data, flamechart, height, width }) { + const canvasRef = useRef(); + + const state = usePanAndZoom({ + canvasRef, + canvasHeight: height, + canvasWidth: width, + fixedColumnWidth: LABEL_FIXED_WIDTH, + fixedHeaderHeight: HEADER_HEIGHT_FIXED, + unscaledContentWidth: data != null ? data.duration : 0, + unscaledContentHeight: + data != null + ? REACT_DEVTOOLS_CANVAS_HEIGHT + + flamechart.layers.length * FLAMECHART_FRAME_HEIGHT + : 0, + }); + + const hoveredEvent = getHoveredEvent(data, flamechart, state); + + useLayoutEffect(() => { + renderCanvas( + data, + flamechart, + canvasRef.current, + width, + height, + state, + hoveredEvent + ); + }); + + return ( + + + + + ); +} + +export default App; diff --git a/src/Canvas.js b/src/Canvas.js new file mode 100644 index 0000000000000..f8ecb0f6d999f --- /dev/null +++ b/src/Canvas.js @@ -0,0 +1,30 @@ +import React, { Fragment, useLayoutEffect, useRef } from 'react'; +import usePanAndZoom from './usePanAndZoom'; + +export default function Canvas({ + height, + renderCanvas, + renderTooltip, + scrollWidth, + width, +}) { + const canvasRef = useRef(); + + const state = usePanAndZoom(canvasRef, scrollWidth); + + useLayoutEffect(() => renderCanvas(canvasRef.current, state)); + + return ( + + + {renderTooltip(state)} +
{`canvas width: ${canvasRef.current ? canvasRef.current.width : '-'}
+canvas scrollWidth: ${canvasRef.current ? scrollWidth : '-'}
+centerX: ${state.centerX}
+zoomLevel: ${state.zoomLevel}
+canvasMouseX: ${state.canvasMouseX}
+canvasMouseY: ${state.canvasMouseY}
+caltulated ts: ${ts}`}
+
+ ); +} diff --git a/src/EventTooltip.css b/src/EventTooltip.css new file mode 100644 index 0000000000000..660e7f6df34bb --- /dev/null +++ b/src/EventTooltip.css @@ -0,0 +1,64 @@ +.Tooltip { + position: absolute; + display: inline-block; + border-radius: 0.125rem; + padding: 0.25rem; + user-select: none; + pointer-events: none; + background-color: #ffffff; + border: 1px solid #ccc; + box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.2); + font-size: 11px; +} + +.Divider { + height: 1px; + background-color: #aaa; + margin: 0.5rem 0; +} + +.DetailsGrid { + display: grid; + padding-top: 5px; + grid-gap: 2px 5px; + grid-template-columns: min-content auto; +} + +.DetailsGridLabel { + color: #666; + text-align: right; + white-space: nowrap; +} + +.Duration { +} + +.ComponentName { +} + +.ComponentName { + font-weight: bold; +} + +.ComponentStack { + overflow: hidden; + max-width: 35em; + max-height: 10em; + margin: 0; + font-size: 0.9em; + line-height: 1.5; + -webkit-mask-image: linear-gradient( + 180deg, + #fff, + #fff var(--gradient-height), + transparent + ); + mask-image: linear-gradient( + 180deg, + #fff, + #fff var(--gradient-height), + transparent + ); + white-space: pre; + --gradient-height: 5em; +} diff --git a/src/EventTooltip.js b/src/EventTooltip.js new file mode 100644 index 0000000000000..92287093742fa --- /dev/null +++ b/src/EventTooltip.js @@ -0,0 +1,216 @@ +// @flow + +import prettyMilliseconds from 'pretty-ms'; +import React, { useLayoutEffect, useRef } from 'react'; +import { COLORS } from './constants'; +import { getBatchRange } from './utils'; +import useSmartTooltip from './useSmartTooltip'; +import styles from './EventTooltip.css'; + +const TOOLTIP_OFFSET = 4; + +export default function EventTooltip({ data, hoveredEvent, state }) { + const { canvasMouseY, canvasMouseX } = state; + + const tooltipRef = useSmartTooltip({ + mouseX: canvasMouseX, + mouseY: canvasMouseY, + }); + + if (hoveredEvent === null) { + return null; + } + + const { event, flamechartNode, measure } = hoveredEvent; + + if (event !== null) { + switch (event.type) { + case 'schedule-render': + return ( + + ); + case 'schedule-state-update': // eslint-disable-line no-case-declarations + const color = event.isCascading + ? COLORS.REACT_SCHEDULE_CASCADING_HOVER + : COLORS.REACT_SCHEDULE_HOVER; + return ( + + ); + case 'suspend': + return ( + + ); + default: + console.warn(`Unexpected event type "${event.type}"`); + break; + } + } else if (measure !== null) { + switch (measure.type) { + case 'commit': + case 'render-idle': + case 'render': + case 'layout-effects': + case 'passive-effects': + return ( + + ); + default: + console.warn(`Unexpected measure type "${measure.type}"`); + break; + } + } else if (flamechartNode !== null) { + return ( + + ); + } else { + return null; + } +} + +function formatComponentStack(componentStack) { + const lines = componentStack.split('\n').map(line => line.trim()); + lines.shift(); + + if (lines.length > 5) { + return lines.slice(0, 5).join('\n') + '\n...'; + } + return lines.join('\n'); +} + +const TooltipFlamechartNode = ({ data, flamechartNode, tooltipRef }) => { + const { end, node, start } = flamechartNode; + const { name, file } = node.frame; + return ( +
+ {prettyMilliseconds((end - start) / 1000)} {name} +
+
Script URL:
+ {file} +
+
+ ); +}; + +const TooltipReactEvent = ({ color, data, event, tooltipRef }) => { + const { componentName, componentStack, timestamp, type } = event; + + let label = null; + switch (type) { + case 'schedule-render': + label = 'render scheduled'; + break; + case 'schedule-state-update': + label = 'state update scheduled'; + break; + case 'suspend': + label = 'suspended'; + break; + default: + break; + } + + return ( +
+ {componentName && ( + + {componentName} + + )}{' '} + {label} +
+
+
Timestamp:
+ {prettyMilliseconds(timestamp)} +
Component stack:
+
+          {formatComponentStack(componentStack)}
+        
+
+
+ ); +}; + +const TooltipReactMeasure = ({ data, measure, tooltipRef }) => { + const { batchUID, duration, priority, timestamp, type } = measure; + + let label = null; + switch (type) { + case 'commit': + label = 'commit'; + break; + case 'render-idle': + label = 'idle'; + break; + case 'render': + label = 'render'; + break; + case 'layout-effects': + label = 'layout effects'; + break; + case 'passive-effects': + label = 'passive effects'; + break; + default: + break; + } + + const [startTime, stopTime] = getBatchRange(batchUID, priority, data); + + return ( +
+ {prettyMilliseconds(duration)} {label} +
+
+
Timestamp:
+ {prettyMilliseconds(timestamp)} +
Batch duration:
+ {prettyMilliseconds(stopTime - startTime)} +
+
+ ); +}; diff --git a/src/SelectedEvent.js b/src/SelectedEvent.js new file mode 100644 index 0000000000000..3843dcaeaedfd --- /dev/null +++ b/src/SelectedEvent.js @@ -0,0 +1,47 @@ +import React from 'react'; +import styles from './SelectedEvent.module.css'; + +export default function SelectedEvent({ selectedEvent, width }) { + if (selectedEvent == null) { + return null; + } + + const { componentStack, duration, timestamp, type } = selectedEvent; + + let label = null; + switch (type) { + case 'commit-work': + label = 'commit'; + break; + case 'non-react-function-call': + label = 'other script'; + break; + case 'render-idle': + label = 'idle'; + break; + case 'render-work': + label = 'render'; + break; + case 'schedule-render': + label = 'render scheduled'; + break; + case 'schedule-state-update': + label = `state update scheduled`; + break; + case 'suspend': + label = `suspended`; + break; + default: + break; + } + + return ( +
+ {label} {duration !== undefined ? `for ${duration}ms` : ''} at {timestamp} + ms + {componentStack && ( +
 {componentStack.trim()}
+ )} +
+ ); +} diff --git a/src/SelectedEvent.module.css b/src/SelectedEvent.module.css new file mode 100644 index 0000000000000..5021ee0f492da --- /dev/null +++ b/src/SelectedEvent.module.css @@ -0,0 +1,11 @@ +.SelectedEvent { + height: auto; + max-height: 100px; + overflow: auto; + background: #fff; + padding: 0 0.5rem; +} + +.ComponentStack { + font-size: 10px; +} diff --git a/src/canvasUtils.js b/src/canvasUtils.js new file mode 100644 index 0000000000000..b4b39fbc8e38c --- /dev/null +++ b/src/canvasUtils.js @@ -0,0 +1,34 @@ +import memoize from 'memoize-one'; + +// hidpi canvas: https://www.html5rocks.com/en/tutorials/canvas/hidpi/ +export function configureRetinaCanvas(canvas, height, width) { + const dpr = window.devicePixelRatio || 1; + canvas.width = width * dpr; + canvas.height = height * dpr; + canvas.style.width = `${width}px`; + canvas.style.height = `${height}px`; + return dpr; +} + +export const getCanvasContext = memoize( + (canvas, height, width, scaleCanvas = true) => { + const context = canvas.getContext('2d', { alpha: false }); + if (scaleCanvas) { + const dpr = configureRetinaCanvas(canvas, height, width); + // Scale all drawing operations by the dpr, so you don't have to worry about the difference. + context.scale(dpr, dpr); + } + return context; + } +); + +export function getCanvasMousePos(canvas, mouseEvent) { + const rect = + canvas instanceof HTMLCanvasElement + ? canvas.getBoundingClientRect() + : { left: 0, top: 0 }; + const canvasMouseX = mouseEvent.clientX - rect.left; + const canvasMouseY = mouseEvent.clientY - rect.top; + + return { canvasMouseX, canvasMouseY }; +} diff --git a/src/constants.js b/src/constants.js new file mode 100644 index 0000000000000..b51930b3405ed --- /dev/null +++ b/src/constants.js @@ -0,0 +1,57 @@ +export const LABEL_SIZE = 120; +export const LABEL_FONT_SIZE = 14; +export const MARKER_HEIGHT = 20; +export const MARKER_TICK_HEIGHT = 8; +export const MARKER_FONT_SIZE = 10; +export const MARKER_GUTTER_SIZE = 4; +export const MARKER_TEXT_PADDING = 8; +export const BAR_HEIGHT = 16; +export const BAR_HORIZONTAL_SPACING = 1; +export const BAR_SPACER_SIZE = 6; +export const EVENT_SIZE = 6; +export const MIN_BAR_WIDTH = 1; +export const SECTION_GUTTER_SIZE = 4; + +export const INTERVAL_TIMES = [10, 20, 50, 100, 200, 500, 1000, 2000, 5000]; +export const MIN_INTERVAL_SIZE_PX = 70; +export const MAX_INTERVAL_SIZE_PX = 140; + +export const MOVE_WHEEL_DELTA_THRESHOLD = 1; +export const ZOOM_WHEEL_DELTA_THRESHOLD = 1; +export const MIN_ZOOM_LEVEL = 0.25; +export const MAX_ZOOM_LEVEL = 1000; + +export const COLORS = { + BACKGROUND: '#ffffff', + FLAME_GRAPH: '#fff79f', + FLAME_GRAPH_HOVER: '#ffe900', + OTHER_SCRIPT: '#fff791', + OTHER_SCRIPT_HOVER: '#ffea00', + PRIORITY_BACKGROUND: '#ededf0', + PRIORITY_BORDER: '#d7d7db', + PRIORITY_LABEL: '#272727', + REACT_IDLE: '#edf6ff', + REACT_IDLE_SELECTED: '#EDF6FF', + REACT_IDLE_HOVER: '#EDF6FF', + REACT_RENDER: '#9fc3f3', + REACT_RENDER_SELECTED: '#64A9F5', + REACT_RENDER_HOVER: '#298ff6', + REACT_COMMIT: '#ff718e', + REACT_COMMIT_SELECTED: '#FF5277', + REACT_COMMIT_HOVER: '#ff335f', + REACT_LAYOUT_EFFECTS: '#c49edd', + REACT_LAYOUT_EFFECTS_SELECTED: '#934FC1', + REACT_LAYOUT_EFFECTS_HOVER: '#6200a4', + REACT_PASSIVE_EFFECTS: '#c49edd', + REACT_PASSIVE_EFFECTS_SELECTED: '#934FC1', + REACT_PASSIVE_EFFECTS_HOVER: '#6200a4', + REACT_SCHEDULE: '#9fc3f3', + REACT_SCHEDULE_HOVER: '#298ff6', + REACT_SCHEDULE_CASCADING: '#ff718e', + REACT_SCHEDULE_CASCADING_HOVER: '#ff335f', + REACT_SUSPEND: '#a6e59f', + REACT_SUSPEND_HOVER: '#13bc00', + REACT_WORK_BORDER: '#ffffff', + TIME_MARKER_LINE: '#CAD6DE', + TIME_MARKER_LABEL: '#18212b', +}; diff --git a/src/contexts.js b/src/contexts.js new file mode 100644 index 0000000000000..4c2bd2abe796b --- /dev/null +++ b/src/contexts.js @@ -0,0 +1,4 @@ +import { createContext } from 'react'; + +export const PriorityContext = createContext(null); +export const TimeRangeContext = createContext([0, 0]); diff --git a/src/index.css b/src/index.css new file mode 100644 index 0000000000000..ec2585e8c0bb8 --- /dev/null +++ b/src/index.css @@ -0,0 +1,13 @@ +body { + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', + 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +code { + font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', + monospace; +} diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000000000..0e636c9b8e253 --- /dev/null +++ b/src/index.js @@ -0,0 +1,8 @@ +import { createElement } from 'react'; +import { render } from 'react-dom'; +import App from './App'; +import './index.css'; + +const container = document.getElementById('root'); + +render(createElement(App), container); diff --git a/src/logo.svg b/src/logo.svg new file mode 100644 index 0000000000000..2e5df0d3ab2f2 --- /dev/null +++ b/src/logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/preprocessData.js b/src/preprocessData.js new file mode 100644 index 0000000000000..1f9bfb23b682c --- /dev/null +++ b/src/preprocessData.js @@ -0,0 +1,298 @@ +// @flow + +import type { + BatchUID, + ReactPriority, + ReactProfilerData, + ReactProfilerDataPriority, +} from './types'; + +// TODO Combine yields/starts that are closer than some threshold with the previous event to reduce renders. + +type Metadata = {| + nextRenderShouldGenerateNewBatchID: boolean, + batchUID: BatchUID, + +stack: Array, +|}; + +export default function reactProfilerProcessor( + rawData: Array +): ReactProfilerData { + const reactProfilerData = { + startTime: rawData[0].ts, + duration: 0, + high: { + events: [], + measures: [], + }, + normal: { + events: [], + measures: [], + }, + low: { + events: [], + measures: [], + }, + unscheduled: { + events: [], + measures: [], + }, + }; + + let currentMetadata = null; + let currentPriority = 'unscheduled'; + let currentProfilerDataGroup = null; + let uidCounter = 0; + + const metadata = { + high: { + nextRenderShouldGenerateNewBatchID: true, + batchUID: 0, + stack: [], + }, + normal: { + nextRenderShouldGenerateNewBatchID: true, + batchUID: 0, + stack: [], + }, + low: { + nextRenderShouldGenerateNewBatchID: true, + batchUID: 0, + stack: [], + }, + unscheduled: { + nextRenderShouldGenerateNewBatchID: true, + batchUID: 0, + stack: [], + }, + }; + + const getLastType = () => { + const { stack } = currentMetadata; + if (stack.length > 0) { + const { type } = stack[stack.length - 1]; + return type; + } + return null; + }; + + const getDepth = () => { + const { stack } = currentMetadata; + if (stack.length > 0) { + const { depth, type } = stack[stack.length - 1]; + return type === 'render-idle' ? depth : depth + 1; + } + return 0; + }; + + const markWorkCompleted = (type, stopTime) => { + const { stack } = currentMetadata; + if (stack.length === 0) { + console.error( + `Unexpected type "${type}" completed while stack is empty.` + ); + } else { + const last = stack[stack.length - 1]; + if (last.type !== type) { + console.error( + `Unexpected type "${type}" completed before "${last.type}" completed.` + ); + } else { + const { index, startTime } = stack.pop(); + + if (currentProfilerDataGroup) { + const measure = currentProfilerDataGroup.measures[index]; + if (!measure) { + console.error( + `Could not find matching measure for type "${type}".` + ); + } else { + // $FlowFixMe This property should not be writable outside of this function. + measure.duration = stopTime - startTime; + } + } + } + } + }; + + const markWorkStarted = (type, startTime) => { + const { batchUID, stack } = currentMetadata; + + const index = currentProfilerDataGroup.measures.length; + const depth = getDepth(); + + stack.push({ + depth, + index, + startTime, + type, + }); + + currentProfilerDataGroup.measures.push({ + type, + batchUID, + depth, + priority: currentPriority, + timestamp: startTime, + duration: 0, + }); + }; + + const throwIfIncomplete = type => { + const { stack } = currentMetadata; + const lastIndex = stack.length - 1; + if (lastIndex >= 0) { + const last = stack[lastIndex]; + if (last.stopTime === undefined && last.type === type) { + throw new Error( + `Unexpected type "${type}" started before "${last.type}" completed.` + ); + } + } + }; + + for (let i = 0; i < rawData.length; i++) { + const currentEvent = rawData[i]; + + const { cat, name, ts } = currentEvent; + + if (cat !== 'blink.user_timing' || !name.startsWith('--')) { + continue; + } + + currentMetadata = metadata[currentPriority] || metadata.unscheduled; + if (!currentMetadata) { + console.error('Unexpected priority', currentPriority); + } + + currentProfilerDataGroup = + reactProfilerData[currentPriority || 'unscheduled']; + if (!currentProfilerDataGroup) { + console.error('Unexpected priority', currentPriority); + } + + const startTime = (ts - reactProfilerData.startTime) / 1000; + + if (name.startsWith('--scheduler-start-')) { + if (currentPriority !== 'unscheduled') { + console.error( + `Unexpected scheduler start: "${name}" with current priority: "${currentPriority}"` + ); + continue; // TODO Should we throw? Will this corrupt our data? + } + + currentPriority = ((name.substr(18): any): ReactPriority); + } else if (name.startsWith('--scheduler-stop-')) { + if ( + currentPriority === 'unscheduled' || + currentPriority !== name.substr(17) + ) { + console.error( + `Unexpected scheduler stop: "${name}" with current priority: "${currentPriority}"` + ); + continue; // TODO Should we throw? Will this corrupt our data? + } + + currentPriority = 'unscheduled'; + } else if (name === '--render-start') { + if (currentMetadata.nextRenderShouldGenerateNewBatchID) { + currentMetadata.nextRenderShouldGenerateNewBatchID = false; + currentMetadata.batchUID = ((uidCounter++: any): BatchUID); + } + throwIfIncomplete('render'); + if (getLastType() !== 'render-idle') { + markWorkStarted('render-idle', startTime); + } + markWorkStarted('render', startTime); + } else if (name === '--render-stop') { + markWorkCompleted('render', startTime); + } else if (name === '--render-yield') { + markWorkCompleted('render', startTime); + } else if (name === '--render-cancel') { + currentMetadata.nextRenderShouldGenerateNewBatchID = true; + markWorkCompleted('render', startTime); + markWorkCompleted('render-idle', startTime); + } else if (name === '--commit-start') { + currentMetadata.nextRenderShouldGenerateNewBatchID = true; + markWorkStarted('commit', startTime); + } else if (name === '--commit-stop') { + markWorkCompleted('commit', startTime); + markWorkCompleted('render-idle', startTime); + } else if ( + name === '--layout-effects-start' || + name === '--passive-effects-start' + ) { + const type = + name === '--layout-effects-start' + ? 'layout-effects' + : 'passive-effects'; + throwIfIncomplete(type); + markWorkStarted(type, startTime); + } else if ( + name === '--layout-effects-stop' || + name === '--passive-effects-stop' + ) { + const type = + name === '--layout-effects-stop' ? 'layout-effects' : 'passive-effects'; + markWorkCompleted(type, startTime); + } else if (name.startsWith('--schedule-render')) { + currentProfilerDataGroup.events.push({ + type: 'schedule-render', + priority: currentPriority, // TODO Change to target priority + timestamp: startTime, + }); + } else if (name.startsWith('--schedule-state-update-')) { + const [componentName, componentStack] = name.substr(24).split('-'); + const isCascading = !!currentMetadata.stack.find( + ({ type }) => type === 'commit' + ); + currentProfilerDataGroup.events.push({ + type: 'schedule-state-update', + priority: currentPriority, // TODO Change to target priority + isCascading, + timestamp: startTime, + componentName, + componentStack, + }); + } else if (name.startsWith('--suspend-')) { + const [componentName, componentStack] = name.substr(10).split('-'); + currentProfilerDataGroup.events.push({ + type: 'suspend', + priority: currentPriority, // TODO Change to target priority + timestamp: startTime, + componentName, + componentStack, + }); + } + } + + Object.entries(metadata).forEach(([priority, metadata]) => { + const { stack } = ((metadata: any): Metadata); + if (stack.length > 0) { + console.error( + `Incomplete events or measures for priority ${priority}`, + stack + ); + } + }); + + ['unscheduled', 'high', 'normal', 'low'].forEach(priority => { + const { events, measures } = reactProfilerData[priority]; + if (events.length > 0) { + const { timestamp } = events[events.length - 1]; + reactProfilerData.duration = Math.max( + reactProfilerData.duration, + timestamp + ); + } + if (measures.length > 0) { + const { duration, timestamp } = measures[measures.length - 1]; + reactProfilerData.duration = Math.max( + reactProfilerData.duration, + timestamp + duration + ); + } + }); + + return reactProfilerData; +} diff --git a/src/preprocessFlamechart.js b/src/preprocessFlamechart.js new file mode 100644 index 0000000000000..de2e4c0c2b5f1 --- /dev/null +++ b/src/preprocessFlamechart.js @@ -0,0 +1,21 @@ +// @flow + +import { importFromChromeTimeline } from './speedscope/import/chrome'; +import { Flamechart } from './speedscope/lib/flamechart'; + +import type { FlamechartData } from './types'; + +export default function preprocessFlamechart( + rawData: Array +): FlamechartData { + const parsedData = importFromChromeTimeline(rawData, 'react-devtools'); + const profile = parsedData.profiles[0]; // TODO Choose the main CPU thread only + const flamechart = new Flamechart({ + getTotalWeight: profile.getTotalWeight.bind(profile), + forEachCall: profile.forEachCall.bind(profile), + formatValue: profile.formatValue.bind(profile), + getColorBucketForFrame: () => null, + }); + + return flamechart; +} diff --git a/src/serviceWorker.js b/src/serviceWorker.js new file mode 100644 index 0000000000000..f8c7e50c20176 --- /dev/null +++ b/src/serviceWorker.js @@ -0,0 +1,135 @@ +// This optional code is used to register a service worker. +// register() is not called by default. + +// This lets the app load faster on subsequent visits in production, and gives +// it offline capabilities. However, it also means that developers (and users) +// will only see deployed updates on subsequent visits to a page, after all the +// existing tabs open on the page have been closed, since previously cached +// resources are updated in the background. + +// To learn more about the benefits of this model and instructions on how to +// opt-in, read https://bit.ly/CRA-PWA + +const isLocalhost = Boolean( + window.location.hostname === 'localhost' || + // [::1] is the IPv6 localhost address. + window.location.hostname === '[::1]' || + // 127.0.0.1/8 is considered localhost for IPv4. + window.location.hostname.match( + /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ + ) +); + +export function register(config) { + if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { + // The URL constructor is available in all browsers that support SW. + const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href); + if (publicUrl.origin !== window.location.origin) { + // Our service worker won't work if PUBLIC_URL is on a different origin + // from what our page is served on. This might happen if a CDN is used to + // serve assets; see https://github.com/facebook/create-react-app/issues/2374 + return; + } + + window.addEventListener('load', () => { + const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; + + if (isLocalhost) { + // This is running on localhost. Let's check if a service worker still exists or not. + checkValidServiceWorker(swUrl, config); + + // Add some additional logging to localhost, pointing developers to the + // service worker/PWA documentation. + navigator.serviceWorker.ready.then(() => { + console.log( + 'This web app is being served cache-first by a service ' + + 'worker. To learn more, visit https://bit.ly/CRA-PWA' + ); + }); + } else { + // Is not localhost. Just register service worker + registerValidSW(swUrl, config); + } + }); + } +} + +function registerValidSW(swUrl, config) { + navigator.serviceWorker + .register(swUrl) + .then(registration => { + registration.onupdatefound = () => { + const installingWorker = registration.installing; + if (installingWorker == null) { + return; + } + installingWorker.onstatechange = () => { + if (installingWorker.state === 'installed') { + if (navigator.serviceWorker.controller) { + // At this point, the updated precached content has been fetched, + // but the previous service worker will still serve the older + // content until all client tabs are closed. + console.log( + 'New content is available and will be used when all ' + + 'tabs for this page are closed. See https://bit.ly/CRA-PWA.' + ); + + // Execute callback + if (config && config.onUpdate) { + config.onUpdate(registration); + } + } else { + // At this point, everything has been precached. + // It's the perfect time to display a + // "Content is cached for offline use." message. + console.log('Content is cached for offline use.'); + + // Execute callback + if (config && config.onSuccess) { + config.onSuccess(registration); + } + } + } + }; + }; + }) + .catch(error => { + console.error('Error during service worker registration:', error); + }); +} + +function checkValidServiceWorker(swUrl, config) { + // Check if the service worker can be found. If it can't reload the page. + fetch(swUrl) + .then(response => { + // Ensure service worker exists, and that we really are getting a JS file. + const contentType = response.headers.get('content-type'); + if ( + response.status === 404 || + (contentType != null && contentType.indexOf('javascript') === -1) + ) { + // No service worker found. Probably a different app. Reload the page. + navigator.serviceWorker.ready.then(registration => { + registration.unregister().then(() => { + window.location.reload(); + }); + }); + } else { + // Service worker found. Proceed as normal. + registerValidSW(swUrl, config); + } + }) + .catch(() => { + console.log( + 'No internet connection found. App is running in offline mode.' + ); + }); +} + +export function unregister() { + if ('serviceWorker' in navigator) { + navigator.serviceWorker.ready.then(registration => { + registration.unregister(); + }); + } +} diff --git a/src/speedscope/README.md b/src/speedscope/README.md new file mode 100644 index 0000000000000..6b116be77c71f --- /dev/null +++ b/src/speedscope/README.md @@ -0,0 +1 @@ +https://github.com/jlfwong/speedscope/ \ No newline at end of file diff --git a/src/speedscope/import/chrome.js b/src/speedscope/import/chrome.js new file mode 100644 index 0000000000000..0ba96ab8d167c --- /dev/null +++ b/src/speedscope/import/chrome.js @@ -0,0 +1,228 @@ +import {Profile, FrameInfo, CallTreeProfileBuilder, ProfileGroup} from '../lib/profile' +import {getOrInsert, lastOf, sortBy, itForEach} from '../lib/utils' +import {TimeFormatter} from '../lib/value-formatters' +import {chromeTreeToNodes, OldCPUProfile} from './v8cpuFormatter' + +// See: https://github.com/v8/v8/blob/master/src/inspector/js_protocol.json + +export function isChromeTimeline(rawProfile) { + if (!Array.isArray(rawProfile)) + return false; + if (rawProfile.length < 1) + return false; + const first = rawProfile[0]; + if (!('pid' in first && 'tid' in first && 'ph' in first && 'cat' in first)) + return false; + if (!rawProfile.find(e => e.name === 'CpuProfile' || e.name === 'Profile' || e.name === 'ProfileChunk')) + return false; + return true; +} +export function importFromChromeTimeline(events, fileName) { + // It seems like sometimes Chrome timeline files contain multiple CpuProfiles? + // For now, choose the first one in the list. + const cpuProfileByID = new Map(); + // Maps profile IDs (like "0x3") to pid/tid pairs formatted as `${pid}:${tid}` + const pidTidById = new Map(); + // Maps pid/tid pairs to thread names + const threadNameByPidTid = new Map(); + // The events aren't necessarily recorded in chronological order. Sort them so + // that they are. + sortBy(events, e => e.ts); + for (let event of events) { + if (event.name === 'CpuProfile') { + const pidTid = `${event.pid}:${event.tid}`; + const id = event.id || pidTid; + cpuProfileByID.set(id, event.args.data.cpuProfile); + pidTidById.set(id, pidTid); + } + if (event.name === 'Profile') { + const pidTid = `${event.pid}:${event.tid}`; + cpuProfileByID.set(event.id || pidTid, Object.assign({ startTime: 0, endTime: 0, nodes: [], samples: [], timeDeltas: [] }, event.args.data)); + if (event.id) { + pidTidById.set(event.id, `${event.pid}:${event.tid}`); + } + } + if (event.name === 'thread_name') { + threadNameByPidTid.set(`${event.pid}:${event.tid}`, event.args.name); + } + if (event.name === 'ProfileChunk') { + const pidTid = `${event.pid}:${event.tid}`; + const cpuProfile = cpuProfileByID.get(event.id || pidTid); + if (cpuProfile) { + const chunk = event.args.data; + if (chunk.cpuProfile) { + if (chunk.cpuProfile.nodes) { + cpuProfile.nodes = cpuProfile.nodes.concat(chunk.cpuProfile.nodes); + } + if (chunk.cpuProfile.samples) { + cpuProfile.samples = cpuProfile.samples.concat(chunk.cpuProfile.samples); + } + } + if (chunk.timeDeltas) { + cpuProfile.timeDeltas = cpuProfile.timeDeltas.concat(chunk.timeDeltas); + } + if (chunk.startTime != null) { + cpuProfile.startTime = chunk.startTime; + } + if (chunk.endTime != null) { + cpuProfile.endTime = chunk.endTime; + } + } + else { + console.warn(`Ignoring ProfileChunk for undeclared Profile with id ${event.id || pidTid}`); + } + } + } + if (cpuProfileByID.size > 0) { + const profiles = []; + let indexToView = 0; + itForEach(cpuProfileByID.keys(), profileId => { + let threadName = null; + let pidTid = pidTidById.get(profileId); + if (pidTid) { + threadName = threadNameByPidTid.get(pidTid) || null; + if (threadName) { + } + } + const profile = importFromChromeCPUProfile(cpuProfileByID.get(profileId)); + if (threadName && cpuProfileByID.size > 1) { + profile.setName(`${fileName} - ${threadName}`); + if (threadName === 'CrRendererMain') { + indexToView = profiles.length; + } + } + else { + profile.setName(`${fileName}`); + } + profiles.push(profile); + }); + return { name: fileName, indexToView, profiles }; + } + else { + throw new Error('Could not find CPU profile in Timeline'); + } +} +const callFrameToFrameInfo = new Map(); +function frameInfoForCallFrame(callFrame) { + return getOrInsert(callFrameToFrameInfo, callFrame, callFrame => { + const name = callFrame.functionName || '(anonymous)'; + const file = callFrame.url; + const line = callFrame.lineNumber; + const col = callFrame.columnNumber; + return { + key: `${name}:${file}:${line}:${col}`, + name, + file, + line, + col, + }; + }); +} +function shouldIgnoreFunction(callFrame) { + const { functionName, url } = callFrame; + if (url === 'native dummy.js') { + // I'm not really sure what this is about, but this seems to be used + // as a way of avoiding edge cases in V8's implementation. + // See: https://github.com/v8/v8/blob/b8626ca4/tools/js2c.py#L419-L424 + return true; + } + return functionName === '(root)' || functionName === '(idle)'; +} +function shouldPlaceOnTopOfPreviousStack(functionName) { + return functionName === '(garbage collector)' || functionName === '(program)'; +} +export function importFromChromeCPUProfile(chromeProfile) { + const profile = new CallTreeProfileBuilder(chromeProfile.endTime - chromeProfile.startTime); + const nodeById = new Map(); + for (let node of chromeProfile.nodes) { + nodeById.set(node.id, node); + } + for (let node of chromeProfile.nodes) { + if (typeof node.parent === 'number') { + node.parent = nodeById.get(node.parent); + } + if (!node.children) + continue; + for (let childId of node.children) { + const child = nodeById.get(childId); + if (!child) + continue; + child.parent = node; + } + } + const samples = []; + const sampleTimes = []; + // The first delta is relative to the profile startTime. + // Ref: https://github.com/v8/v8/blob/44bd8fd7/src/inspector/js_protocol.json#L1485 + let elapsed = chromeProfile.timeDeltas[0]; + let lastNodeId = NaN; + // The chrome CPU profile format doesn't collapse identical samples. We'll do that + // here to save a ton of work later doing mergers. + for (let i = 0; i < chromeProfile.samples.length; i++) { + const nodeId = chromeProfile.samples[i]; + if (nodeId != lastNodeId) { + samples.push(nodeId); + sampleTimes.push(elapsed); + } + if (i === chromeProfile.samples.length - 1) { + if (!isNaN(lastNodeId)) { + samples.push(lastNodeId); + sampleTimes.push(elapsed); + } + } + else { + let timeDelta = chromeProfile.timeDeltas[i + 1]; + if (timeDelta < 0) { + // This is super noisy, but can be helpful when debugging strange data + // console.warn('Substituting zero for unexpected time delta:', timeDelta, 'at index', i) + timeDelta = 0; + } + elapsed += timeDelta; + lastNodeId = nodeId; + } + } + let prevStack = []; + for (let i = 0; i < samples.length; i++) { + const value = sampleTimes[i]; + const nodeId = samples[i]; + let stackTop = nodeById.get(nodeId); + if (!stackTop) + continue; + // Find lowest common ancestor of the current stack and the previous one + let lca = null; + // This is O(n^2), but n should be relatively small here (stack height), + // so hopefully this isn't much of a problem + for (lca = stackTop; lca && prevStack.indexOf(lca) === -1; lca = shouldPlaceOnTopOfPreviousStack(lca.callFrame.functionName) + ? lastOf(prevStack) + : lca.parent || null) { } + // Close frames that are no longer open + while (prevStack.length > 0 && lastOf(prevStack) != lca) { + const closingNode = prevStack.pop(); + const frame = frameInfoForCallFrame(closingNode.callFrame); + profile.leaveFrame(frame, value); + } + // Open frames that are now becoming open + const toOpen = []; + for (let node = stackTop; node && node != lca && !shouldIgnoreFunction(node.callFrame); + // Place Chrome internal functions on top of the previous call stack + node = shouldPlaceOnTopOfPreviousStack(node.callFrame.functionName) + ? lastOf(prevStack) + : node.parent || null) { + toOpen.push(node); + } + toOpen.reverse(); + for (let node of toOpen) { + profile.enterFrame(frameInfoForCallFrame(node.callFrame), value); + } + prevStack = prevStack.concat(toOpen); + } + // Close frames that are open at the end of the trace + for (let i = prevStack.length - 1; i >= 0; i--) { + profile.leaveFrame(frameInfoForCallFrame(prevStack[i].callFrame), lastOf(sampleTimes)); + } + profile.setValueFormatter(new TimeFormatter('microseconds')); + return profile.build(); +} +export function importFromOldV8CPUProfile(content) { + return importFromChromeCPUProfile(chromeTreeToNodes(content)); +} diff --git a/src/speedscope/import/v8cpuFormatter.js b/src/speedscope/import/v8cpuFormatter.js new file mode 100644 index 0000000000000..9443c98d2e2fd --- /dev/null +++ b/src/speedscope/import/v8cpuFormatter.js @@ -0,0 +1,39 @@ +function treeToArray(root) { + const nodes = []; + function visit(node) { + nodes.push({ + id: node.id, + callFrame: { + columnNumber: 0, + functionName: node.functionName, + lineNumber: node.lineNumber, + scriptId: node.scriptId, + url: node.url, + }, + hitCount: node.hitCount, + children: node.children.map(child => child.id), + }); + node.children.forEach(visit); + } + visit(root); + return nodes; +} +function timestampsToDeltas(timestamps, startTime) { + return timestamps.map((timestamp, index) => { + const lastTimestamp = index === 0 ? startTime * 1000000 : timestamps[index - 1]; + return timestamp - lastTimestamp; + }); +} +/** + * Convert the old tree-based format to the new flat-array based format + */ +export function chromeTreeToNodes(content) { + // Note that both startTime and endTime are now in microseconds + return { + samples: content.samples, + startTime: content.startTime * 1000000, + endTime: content.endTime * 1000000, + nodes: treeToArray(content.head), + timeDeltas: timestampsToDeltas(content.timestamps, content.startTime), + }; +} diff --git a/src/speedscope/lib/demangle-cpp.js b/src/speedscope/lib/demangle-cpp.js new file mode 100644 index 0000000000000..c4ec613c95ab3 --- /dev/null +++ b/src/speedscope/lib/demangle-cpp.js @@ -0,0 +1,32 @@ +let cppfilt; +const cache = new Map(); +// This function converts a mangled C++ name such as "__ZNK7Support6ColorFeqERKS0_" +// into a human-readable symbol (in this case "Support::ColorF::==(Support::ColorF&)") +export function demangleCpp(name) { + if (name.startsWith('__Z')) { + let result = cache.get(name); + if (result !== undefined) { + name = result; + } + else { + if (!cppfilt) { + cppfilt = new Function('exports', code)(); + } + result = cppfilt(name.slice(1)); + result = result === '(null)' ? name : result; + cache.set(name, result); + name = result; + } + } + return name; +} + +// This was taken from https://d.fuqu.jp/c++filtjs/ +const code = ` +return function(){function r(r){eval.call(null,r)}function a(r){throw print(r+":\\n"+(new Error).stack),ke=!0,"Assertion: "+r}function e(r,e){r||a("Assertion failed: "+e)}function i(r,a,i,v){function t(r,a){if("string"==a){var e=Oe;return le.stackAlloc(r.length+1),A(r,e),e}return r}function f(r,a){return"string"==a?s(r):r}try{func=ce.Module["_"+r]}catch(r){}e(func,"Cannot call unknown function "+r+" (perhaps LLVM optimizations or closure removed it?)");var _=0,n=v?v.map(function(r){return t(r,i[_++])}):[];return f(func.apply(null,n),a)}function v(r,a,e){return function(){return i(r,a,e,Array.prototype.slice.call(arguments))}}function t(r,e,i,v){switch(i=i||"i8","*"===i[i.length-1]&&(i="i32"),i){case"i1":Ae[r]=e;break;case"i8":Ae[r]=e;break;case"i16":ye[r>>1]=e;break;case"i32":Se[r>>2]=e;break;case"i64":Se[r>>2]=e;break;case"float":Ce[r>>2]=e;break;case"double":ze[0]=e,Se[r>>2]=xe[0],Se[r+4>>2]=xe[1];break;default:a("invalid type for setValue: "+i)}}function f(r,e,i){switch(e=e||"i8","*"===e[e.length-1]&&(e="i32"),e){case"i1":return Ae[r];case"i8":return Ae[r];case"i16":return ye[r>>1];case"i32":return Se[r>>2];case"i64":return Se[r>>2];case"float":return Ce[r>>2];case"double":return xe[0]=Se[r>>2],xe[1]=Se[r+4>>2],ze[0];default:a("invalid type for setValue: "+e)}return null}function _(r,a,e){var i,v;"number"==typeof r?(i=!0,v=r):(i=!1,v=r.length);var f="string"==typeof a?a:null,_=[Jr,le.stackAlloc,le.staticAlloc][void 0===e?we:e](Math.max(v,f?1:a.length));if(i)return Fa(_,0,v),_;for(var s,n=0;n>12<<12}function l(){for(;Le<=Ie;)Le=o(2*Le);var r=Ae,a=new ArrayBuffer(Le);Ae=new Int8Array(a),ye=new Int16Array(a),Se=new Int32Array(a),ge=new Uint8Array(a),me=new Uint16Array(a),Me=new Uint32Array(a),Ce=new Float32Array(a),Re=new Float64Array(a),Ae.set(r)}function b(r){for(;r.length>0;){var a=r.shift(),e=a.func;"number"==typeof e&&(e=pe[e]),e(void 0===a.arg?null:a.arg)}}function k(){b(Ve)}function u(){b(Be),be.print()}function c(r,a){return Array.prototype.slice.call(Ae.subarray(r,r+a))}function h(r,a){for(var e=new Uint8Array(a),i=0;i255&&(v&=255),e.push(v),i+=1}return a||e.push(0),e}function E(r){for(var a=[],e=0;e255&&(i&=255),a.push(String.fromCharCode(i))}return a.join("")}function A(r,a,e){for(var i=0;i255&&(v&=255),Ae[a+i]=v,i+=1}e||(Ae[a+i]=0)}function g(r,a,e,i){return r>=0?r:a<=32?2*Math.abs(1<=v&&(a<=32||r>v)&&(r=-2*v+r),r}function m(r,a,e){if(0==(0|r)|0==(0|a)|0==(0|e))var i=0;else{Se[r>>2]=0,Se[r+4>>2]=a,Se[r+8>>2]=e;var i=1}var i;return i}function S(r,a,e){if(0==(0|r)|(0|a)<0|0==(0|e))var i=0;else{Se[r>>2]=41,Se[r+4>>2]=a,Se[r+8>>2]=e;var i=1}var i;return i}function M(r,a,e){if(0==(0|r)|0==(0|e))var i=0;else{Se[r>>2]=6,Se[r+4>>2]=a,Se[r+8>>2]=e;var i=1}var i;return i}function C(r,a,e){if(0==(0|r)|0==(0|e))var i=0;else{Se[r>>2]=7,Se[r+4>>2]=a,Se[r+8>>2]=e;var i=1}var i;return i}function R(r,a){var e,i=0==(0|a);do if(i)var v=0;else{var e=(r+32|0)>>2,t=Se[e];if((0|t)>=(0|Se[r+36>>2])){var v=0;break}var f=(t<<2)+Se[r+28>>2]|0;Se[f>>2]=a;var _=Se[e]+1|0;Se[e]=_;var v=1}while(0);var v;return v}function T(r,a){var e,e=(r+12|0)>>2,i=Se[e],v=i+1|0;Se[e]=v;var t=Ae[i]<<24>>24==95;do if(t){var f=i+2|0;if(Se[e]=f,Ae[v]<<24>>24!=90){var _=0;break}var s=O(r,a),_=s}else var _=0;while(0);var _;return _}function O(r,a){var e=r+12|0,i=Ae[Se[e>>2]];r:do if(i<<24>>24==71||i<<24>>24==84)var v=Tr(r),t=v;else{var f=Ar(r),_=0==(0|f)|0==(0|a);do if(!_){if(0!=(1&Se[r+8>>2]|0))break;var s=Me[f>>2],n=(s-25|0)>>>0<3;a:do if(n)for(var o=f;;){var o,l=Me[o+4>>2],b=Me[l>>2];if((b-25|0)>>>0>=3){var k=l,u=b;break a}var o=l}else var k=f,u=s;while(0);var u,k;if(2!=(0|u)){var t=k;break r}var c=k+8|0,h=Me[c>>2],d=(Se[h>>2]-25|0)>>>0<3;a:do if(d)for(var w=h;;){var w,p=Me[w+4>>2];if((Se[p>>2]-25|0)>>>0>=3){var E=p;break a}var w=p}else var E=h;while(0);var E;Se[c>>2]=E;var t=k;break r}while(0);var A=Ae[Se[e>>2]];if(A<<24>>24==0||A<<24>>24==69){var t=f;break}var g=Or(f),y=Sr(r,g),m=D(r,3,f,y),t=m}while(0);var t;return t}function N(r){var a,e,i=Oe;Oe+=4;var v=i,e=v>>2,a=(r+12|0)>>2,t=Me[a],f=Ae[t],_=f<<24>>24;r:do if(f<<24>>24==114||f<<24>>24==86||f<<24>>24==75){var s=I(r,v,0);if(0==(0|s)){var n=0;break}var o=N(r);Se[s>>2]=o;var l=Se[e],b=R(r,l);if(0==(0|b)){var n=0;break}var n=Se[e]}else{do{if(97==(0|_)||98==(0|_)||99==(0|_)||100==(0|_)||101==(0|_)||102==(0|_)||103==(0|_)||104==(0|_)||105==(0|_)||106==(0|_)||108==(0|_)||109==(0|_)||110==(0|_)||111==(0|_)||115==(0|_)||116==(0|_)||118==(0|_)||119==(0|_)||120==(0|_)||121==(0|_)||122==(0|_)){var k=ai+20*(_-97)|0,u=P(r,k);Se[e]=u;var c=r+48|0,h=Se[c>>2]+Se[Se[u+4>>2]+4>>2]|0;Se[c>>2]=h;var d=Se[a]+1|0;Se[a]=d;var n=u;break r}if(117==(0|_)){Se[a]=t+1|0;var w=L(r),p=D(r,34,w,0);Se[e]=p;var E=p}else if(70==(0|_)){var A=F(r);Se[e]=A;var E=A}else if(48==(0|_)||49==(0|_)||50==(0|_)||51==(0|_)||52==(0|_)||53==(0|_)||54==(0|_)||55==(0|_)||56==(0|_)||57==(0|_)||78==(0|_)||90==(0|_)){var g=X(r);Se[e]=g;var E=g}else if(65==(0|_)){var y=j(r);Se[e]=y;var E=y}else if(77==(0|_)){var m=U(r);Se[e]=m;var E=m}else if(84==(0|_)){var S=x(r);if(Se[e]=S,Ae[Se[a]]<<24>>24!=73){var E=S;break}var M=R(r,S);if(0==(0|M)){var n=0;break r}var C=Se[e],T=z(r),O=D(r,4,C,T);Se[e]=O;var E=O}else if(83==(0|_)){var B=ge[t+1|0];if((B-48&255&255)<10|B<<24>>24==95|(B-65&255&255)<26){var H=V(r,0);if(Se[e]=H,Ae[Se[a]]<<24>>24!=73){var n=H;break r}var K=z(r),Y=D(r,4,H,K);Se[e]=Y;var E=Y}else{var G=X(r);if(Se[e]=G,0==(0|G)){var E=0;break}if(21==(0|Se[G>>2])){var n=G;break r}var E=G}}else if(80==(0|_)){Se[a]=t+1|0;var W=N(r),Z=D(r,29,W,0);Se[e]=Z;var E=Z}else if(82==(0|_)){Se[a]=t+1|0;var Q=N(r),q=D(r,30,Q,0);Se[e]=q;var E=q}else if(67==(0|_)){Se[a]=t+1|0;var $=N(r),J=D(r,31,$,0);Se[e]=J;var E=J}else if(71==(0|_)){Se[a]=t+1|0;var rr=N(r),ar=D(r,32,rr,0);Se[e]=ar;var E=ar}else{if(85!=(0|_)){var n=0;break r}Se[a]=t+1|0;var er=L(r);Se[e]=er;var ir=N(r),vr=Se[e],tr=D(r,28,ir,vr);Se[e]=tr;var E=tr}}while(0);var E,fr=R(r,E);if(0==(0|fr)){var n=0;break}var n=Se[e]}while(0);var n;return Oe=i,n}function I(r,a,e){for(var i,v=r+12|0,t=0!=(0|e),f=t?25:22,i=(r+48|0)>>2,_=t?26:23,s=t?27:24,n=a;;){var n,o=Se[v>>2],l=Ae[o];if(l<<24>>24!=114&&l<<24>>24!=86&&l<<24>>24!=75){var b=n;break}var k=o+1|0;if(Se[v>>2]=k,l<<24>>24==114){var u=Se[i]+9|0;Se[i]=u;var c=f}else if(l<<24>>24==86){var h=Se[i]+9|0;Se[i]=h;var c=_}else{var d=Se[i]+6|0;Se[i]=d;var c=s}var c,w=D(r,c,0,0);if(Se[n>>2]=w,0==(0|w)){var b=0;break}var n=w+4|0}var b;return b}function P(r,a){var e=0==(0|a);do if(e)var i=0;else{var v=J(r);if(0==(0|v)){var i=0;break}Se[v>>2]=33,Se[v+4>>2]=a;var i=v}while(0);var i;return i}function D(r,a,e,i){var v,t;do{if(1==(0|a)||2==(0|a)||3==(0|a)||4==(0|a)||10==(0|a)||28==(0|a)||37==(0|a)||43==(0|a)||44==(0|a)||45==(0|a)||46==(0|a)||47==(0|a)||48==(0|a)||49==(0|a)||50==(0|a)){if(0==(0|e)|0==(0|i)){var f=0;t=7;break}t=5;break}if(8==(0|a)||9==(0|a)||11==(0|a)||12==(0|a)||13==(0|a)||14==(0|a)||15==(0|a)||16==(0|a)||17==(0|a)||18==(0|a)||19==(0|a)||20==(0|a)||29==(0|a)||30==(0|a)||31==(0|a)||32==(0|a)||34==(0|a)||38==(0|a)||39==(0|a)||42==(0|a)){if(0==(0|e)){var f=0;t=7;break}t=5;break}if(36==(0|a)){if(0==(0|i)){var f=0;t=7;break}t=5;break}if(35==(0|a)||22==(0|a)||23==(0|a)||24==(0|a)||25==(0|a)||26==(0|a)||27==(0|a))t=5;else{var f=0;t=7}}while(0);do if(5==t){var _=J(r),v=_>>2;if(0==(0|_)){var f=0;break}Se[v]=a,Se[v+1]=e,Se[v+2]=i;var f=_}while(0);var f;return f}function L(r){var a=sr(r);if((0|a)<1)var e=0;else{var i=Rr(r,a);Se[r+44>>2]=i;var e=i}var e;return e}function F(r){var a,a=(r+12|0)>>2,e=Se[a],i=e+1|0;if(Se[a]=i,Ae[e]<<24>>24==70){if(Ae[i]<<24>>24==89){var v=e+2|0;Se[a]=v}var t=Sr(r,1),f=Se[a],_=f+1|0;Se[a]=_;var s=Ae[f]<<24>>24==69?t:0,n=s}else var n=0;var n;return n}function X(r){var a=Ar(r);return a}function j(r){var a,a=(r+12|0)>>2,e=Se[a],i=e+1|0;Se[a]=i;var v=Ae[e]<<24>>24==65;do if(v){var t=Ae[i];if(t<<24>>24==95)var f=0;else if((t-48&255&255)<10){for(var _=i;;){var _,s=_+1|0;if(Se[a]=s,(Ae[s]-48&255&255)>=10)break;var _=s}var n=s-i|0,o=lr(r,i,n);if(0==(0|o)){var l=0;break}var f=o}else{var b=nr(r);if(0==(0|b)){var l=0;break}var f=b}var f,k=Se[a],u=k+1|0;if(Se[a]=u,Ae[k]<<24>>24!=95){var l=0;break}var c=N(r),h=D(r,36,f,c),l=h}else var l=0;while(0);var l;return l}function U(r){var a=Oe;Oe+=4;var e=a,i=r+12|0,v=Se[i>>2],t=v+1|0;Se[i>>2]=t;var f=Ae[v]<<24>>24==77;r:do if(f){var _=N(r),s=I(r,e,1);if(0==(0|s)){var n=0;break}var o=N(r);Se[s>>2]=o;var l=(0|s)==(0|e);do if(!l){if(35==(0|Se[o>>2]))break;var b=Se[e>>2],k=R(r,b);if(0==(0|k)){var n=0;break r}}while(0);var u=Se[e>>2],c=D(r,37,_,u),n=c}else var n=0;while(0);var n;return Oe=a,n}function x(r){var a,a=(r+12|0)>>2,e=Se[a],i=e+1|0;Se[a]=i;var v=Ae[e]<<24>>24==84;do if(v){if(Ae[i]<<24>>24==95)var t=0,f=i;else{var _=sr(r);if((0|_)<0){var s=0;break}var t=_+1|0,f=Se[a]}var f,t;if(Se[a]=f+1|0,Ae[f]<<24>>24!=95){var s=0;break}var n=r+40|0,o=Se[n>>2]+1|0;Se[n>>2]=o;var l=Er(r,t),s=l}else var s=0;while(0);var s;return s}function z(r){var a,e=Oe;Oe+=4;var i=e,v=r+44|0,t=Se[v>>2],a=(r+12|0)>>2,f=Se[a],_=f+1|0;Se[a]=_;var s=Ae[f]<<24>>24==73;r:do if(s){Se[i>>2]=0;for(var n=i;;){var n,o=_r(r);if(0==(0|o)){var l=0;break r}var b=D(r,39,o,0);if(Se[n>>2]=b,0==(0|b)){var l=0;break r}var k=Se[a];if(Ae[k]<<24>>24==69)break;var n=b+8|0}var u=k+1|0;Se[a]=u,Se[v>>2]=t;var l=Se[i>>2]}else var l=0;while(0);var l;return Oe=e,l}function V(r,a){var e,e=(r+12|0)>>2,i=Se[e],v=i+1|0;Se[e]=v;var t=Ae[i]<<24>>24==83;r:do if(t){var f=i+2|0;Se[e]=f;var _=ge[v];if(_<<24>>24==95)var s=0;else{if(!((_-48&255&255)<10|(_-65&255&255)<26)){var n=8&Se[r+8>>2],o=n>>>3,l=0!=(0|n)|0==(0|a);do if(l)var b=o;else{if((Ae[f]-67&255&255)>=2){var b=o;break}var b=1}while(0);for(var b,k=0|ei;;){var k;if(k>>>0>=(ei+196|0)>>>0){var u=0;break r}if(_<<24>>24==Ae[0|k]<<24>>24)break;var k=k+28|0}var c=Se[k+20>>2];if(0!=(0|c)){var h=Se[k+24>>2],d=fr(r,c,h);Se[r+44>>2]=d}if(0==(0|b))var w=k+8|0,p=k+4|0;else var w=k+16|0,p=k+12|0;var p,w,E=Se[w>>2],A=Se[p>>2],g=r+48|0,y=Se[g>>2]+E|0;Se[g>>2]=y;var m=fr(r,A,E),u=m;break}for(var S=_,M=0,C=f;;){var C,M,S;if((S-48&255&255)<10)var R=36*M-48|0;else{if((S-65&255&255)>=26){var u=0;break r}var R=36*M-55|0}var R,T=(S<<24>>24)+R|0;if((0|T)<0){var u=0;break r}var O=C+1|0;Se[e]=O;var N=ge[C];if(N<<24>>24==95)break;var S=N,M=T,C=O}var s=T+1|0}var s;if((0|s)>=(0|Se[r+32>>2])){var u=0;break}var I=r+40|0,P=Se[I>>2]+1|0;Se[I>>2]=P;var u=Se[Se[r+28>>2]+(s<<2)>>2]}else var u=0;while(0);var u;return u}function B(r,a,e,i){var v,t,f,_,s=Oe;Oe+=28;var n,o=s,_=o>>2;Se[_]=r;var l=e+1|0,f=(o+12|0)>>2;Se[f]=l;var b=Jr(l),t=(o+4|0)>>2;if(Se[t]=b,0==(0|b))var k=0,u=1;else{var v=(o+8|0)>>2;Se[v]=0,Se[_+4]=0,Se[_+5]=0;var c=o+24|0;Se[c>>2]=0,H(o,a);var h=Me[t],d=0==(0|h);do{if(!d){var w=Me[v];if(w>>>0>=Me[f]>>>0){n=5;break}Se[v]=w+1|0,Ae[h+w|0]=0,n=6;break}n=5}while(0);5==n&&Y(o,0);var p=Se[t],E=0==(0|p)?Se[c>>2]:Se[f],k=p,u=E}var u,k;return Se[i>>2]=u,Oe=s,k}function H(r,a){var e,i,v,t,f,_,s,n,o,l,b,k,u,c,h,d,w,p,E,A,g,y,m,S,M,C,R,T,O,N,I,P,D,L,F,X,j,U,x,z,V,B,K,G,W,J,vr,tr,fr,_r,sr,nr,or,lr,br,kr,ur,cr,hr,dr,wr,pr=a>>2,Er=r>>2,Ar=Oe;Oe+=184;var gr,yr=Ar,wr=yr>>2,mr=Ar+64,dr=mr>>2,Sr=Ar+72,Mr=Ar+88,Cr=Ar+104,hr=Cr>>2,Rr=Ar+168,Tr=0==(0|a);r:do if(Tr)Z(r);else{var cr=(r+4|0)>>2,Or=Me[cr];if(0==(0|Or))break;var Nr=0|a,Ir=Me[Nr>>2];a:do{if(0==(0|Ir)){if(0!=(4&Se[Er]|0)){var Pr=Se[pr+1],Dr=Se[pr+2];q(r,Pr,Dr);break r}var ur=(r+8|0)>>2,Lr=Me[ur],Fr=a+8|0,Xr=Me[Fr>>2];if((Xr+Lr|0)>>>0>Me[Er+3]>>>0){var jr=Se[pr+1];Q(r,jr,Xr);break r}var Ur=Or+Lr|0,xr=Se[pr+1];Pa(Ur,xr,Xr,1);var zr=Se[ur]+Se[Fr>>2]|0;Se[ur]=zr;break r}if(1==(0|Ir)||2==(0|Ir)){var Vr=Se[pr+1];H(r,Vr);var Br=0==(4&Se[Er]|0),Hr=Me[cr],Kr=0!=(0|Hr);e:do if(Br){do if(Kr){var kr=(r+8|0)>>2,Yr=Me[kr];if((Yr+2|0)>>>0>Me[Er+3]>>>0)break;var Gr=Hr+Yr|0;oe=14906,Ae[Gr]=255&oe,oe>>=8,Ae[Gr+1]=255&oe;var Wr=Se[kr]+2|0;Se[kr]=Wr;break e}while(0);Q(r,0|He.__str120,2)}else{do if(Kr){var Zr=r+8|0,Qr=Me[Zr>>2];if(Qr>>>0>=Me[Er+3]>>>0)break;Se[Zr>>2]=Qr+1|0,Ae[Hr+Qr|0]=46;break e}while(0);Y(r,46)}while(0);var qr=Se[pr+2];H(r,qr);break r}if(3==(0|Ir)){for(var br=(r+20|0)>>2,$r=Me[br],lr=(r+16|0)>>2,Jr=a,ra=0,aa=$r;;){var aa,ra,Jr,ea=Me[Jr+4>>2];if(0==(0|ea)){var ia=ra,va=0;gr=33;break}if(ra>>>0>3){Z(r);break r}var ta=(ra<<4)+yr|0;Se[ta>>2]=aa,Se[br]=ta,Se[((ra<<4)+4>>2)+wr]=ea,Se[((ra<<4)+8>>2)+wr]=0;var fa=Me[lr];Se[((ra<<4)+12>>2)+wr]=fa;var _a=ra+1|0,sa=0|ea,na=Me[sa>>2];if((na-25|0)>>>0>=3){gr=25;break}var Jr=ea,ra=_a,aa=ta}e:do if(25==gr){if(4==(0|na)){Se[dr]=fa,Se[lr]=mr,Se[dr+1]=ea;var oa=Se[sa>>2],la=mr}else var oa=na,la=fa;var la,oa;if(2!=(0|oa)){var ia=_a,va=sa;break}for(var ba=_a,ka=ea+8|0;;){var ka,ba,ua=Me[ka>>2];if((Se[ua>>2]-25|0)>>>0>=3){var ia=ba,va=sa;break e}if(ba>>>0>3)break;var ca=(ba<<4)+yr|0,ha=ba-1|0,da=(ha<<4)+yr|0,or=ca>>2,nr=da>>2;Se[or]=Se[nr],Se[or+1]=Se[nr+1],Se[or+2]=Se[nr+2],Se[or+3]=Se[nr+3],Se[ca>>2]=da,Se[br]=ca,Se[((ha<<4)+4>>2)+wr]=ua,Se[((ha<<4)+8>>2)+wr]=0,Se[((ha<<4)+12>>2)+wr]=la;var ba=ba+1|0,ka=ua+4|0}Z(r);break r}while(0);var va,ia,wa=Se[pr+2];if(H(r,wa),4==(0|Se[va>>2])){var pa=Se[dr];Se[lr]=pa}var Ea=0==(0|ia);e:do if(!Ea)for(var Aa=r+8|0,ga=r+12|0,ya=ia;;){var ya,ma=ya-1|0;if(0==(0|Se[((ma<<4)+8>>2)+wr])){var Sa=Me[cr],Ma=0==(0|Sa);do{if(!Ma){var Ca=Me[Aa>>2];if(Ca>>>0>=Me[ga>>2]>>>0){gr=41;break}Se[Aa>>2]=Ca+1|0,Ae[Sa+Ca|0]=32,gr=42;break}gr=41}while(0);41==gr&&Y(r,32);var Ra=Se[((ma<<4)+4>>2)+wr];$(r,Ra)}if(0==(0|ma))break e;var ya=ma}while(0);Se[br]=$r;break r}if(4==(0|Ir)){var sr=(r+20|0)>>2,Ta=Se[sr];Se[sr]=0;var Oa=Se[pr+1];H(r,Oa);var Na=Me[cr],Ia=0==(0|Na);do{if(!Ia){var _r=(r+8|0)>>2,Da=Me[_r],La=0==(0|Da);do if(!La){if(Ae[Na+(Da-1)|0]<<24>>24!=60)break;Da>>>0>>0?(Se[_r]=Da+1|0,Ae[Na+Da|0]=32):Y(r,32)}while(0);var Fa=Me[cr];if(0==(0|Fa)){gr=54;break}var Xa=Me[_r];if(Xa>>>0>=Me[Er+3]>>>0){gr=54;break}Se[_r]=Xa+1|0,Ae[Fa+Xa|0]=60,gr=55;break}gr=54}while(0);54==gr&&Y(r,60);var ja=Se[pr+2];H(r,ja);var Ua=Me[cr],xa=0==(0|Ua);do{if(!xa){var fr=(r+8|0)>>2,za=Me[fr],Va=0==(0|za);do if(!Va){if(Ae[Ua+(za-1)|0]<<24>>24!=62)break;za>>>0>>0?(Se[fr]=za+1|0,Ae[Ua+za|0]=32):Y(r,32)}while(0);var Ba=Me[cr];if(0==(0|Ba)){gr=64;break}var Ha=Me[fr];if(Ha>>>0>=Me[Er+3]>>>0){gr=64;break}Se[fr]=Ha+1|0,Ae[Ba+Ha|0]=62,gr=65;break}gr=64}while(0);64==gr&&Y(r,62),Se[sr]=Ta;break r}if(5==(0|Ir)){var tr=(r+16|0)>>2,Ka=Me[tr];if(0==(0|Ka)){Z(r);break r}for(var Ya=Se[pr+1],Ga=Se[Ka+4>>2];;){var Ga,Ya,Wa=Se[Ga+8>>2];if(0==(0|Wa))break;if(39!=(0|Se[Wa>>2])){Z(r);break r}if((0|Ya)<1){if(0!=(0|Ya))break;var Za=Se[Ka>>2];Se[tr]=Za;var Qa=Se[Wa+4>>2];H(r,Qa),Se[tr]=Ka;break r}var Ya=Ya-1|0,Ga=Wa}Z(r);break r}if(6==(0|Ir)){var qa=Se[pr+2];H(r,qa);break r}if(7==(0|Ir)){var $a=r+8|0,Ja=Me[$a>>2];Ja>>>0>>0?(Se[$a>>2]=Ja+1|0,Ae[Or+Ja|0]=126):Y(r,126);var re=Se[pr+2];H(r,re);break r}if(8==(0|Ir)){var vr=(r+8|0)>>2,ae=Me[vr];if((ae+11|0)>>>0>Me[Er+3]>>>0)Q(r,0|He.__str121,11);else{for(var ee=Or+ae|0,ie=0|He.__str121,ve=ee,te=ie+11;ie>2,se=Me[J];if((se+8|0)>>>0>Me[Er+3]>>>0)Q(r,0|He.__str122,8);else{var ne=Or+se|0,le=0|ne;oe=542397526,Ae[le]=255&oe,oe>>=8,Ae[le+1]=255&oe,oe>>=8,Ae[le+2]=255&oe,oe>>=8,Ae[le+3]=255&oe;var be=ne+4|0;oe=544370534,Ae[be]=255&oe,oe>>=8,Ae[be+1]=255&oe,oe>>=8,Ae[be+2]=255&oe,oe>>=8,Ae[be+3]=255&oe;var ke=Se[J]+8|0;Se[J]=ke}var ue=Se[pr+1];H(r,ue);break r}if(10==(0|Ir)){var W=(r+8|0)>>2,ce=Me[W],he=r+12|0;if((ce+24|0)>>>0>Me[he>>2]>>>0)Q(r,0|He.__str123,24);else{var de=Or+ce|0;Pa(de,0|He.__str123,24,1);var we=Se[W]+24|0;Se[W]=we}var pe=Se[pr+1];H(r,pe);var Ee=Me[cr],ge=0==(0|Ee);do{if(!ge){var ye=Me[W];if((ye+4|0)>>>0>Me[he>>2]>>>0){gr=96;break}var me=Ee+ye|0;oe=762210605,Ae[me]=255&oe,oe>>=8,Ae[me+1]=255&oe,oe>>=8,Ae[me+2]=255&oe,oe>>=8,Ae[me+3]=255&oe;var Ce=Se[W]+4|0;Se[W]=Ce,gr=97;break}gr=96}while(0);96==gr&&Q(r,0|He.__str124,4);var Re=Se[pr+2];H(r,Re);break r}if(11==(0|Ir)){var G=(r+8|0)>>2,Te=Me[G];if((Te+13|0)>>>0>Me[Er+3]>>>0)Q(r,0|He.__str125,13);else{for(var Ne=Or+Te|0,ie=0|He.__str125,ve=Ne,te=ie+13;ie>2,De=Me[K];if((De+18|0)>>>0>Me[Er+3]>>>0)Q(r,0|He.__str126,18);else{for(var Le=Or+De|0,ie=0|He.__str126,ve=Le,te=ie+18;ie>2,je=Me[B];if((je+16|0)>>>0>Me[Er+3]>>>0)Q(r,0|He.__str127,16);else{for(var Ue=Or+je|0,ie=0|He.__str127,ve=Ue,te=ie+16;ie>2,Ve=Me[V];if((Ve+21|0)>>>0>Me[Er+3]>>>0)Q(r,0|He.__str128,21);else{var Be=Or+Ve|0;Pa(Be,0|He.__str128,21,1);var Ke=Se[V]+21|0;Se[V]=Ke}var Ye=Se[pr+1];H(r,Ye);break r}if(15==(0|Ir)){var z=(r+8|0)>>2,Ge=Me[z];if((Ge+17|0)>>>0>Me[Er+3]>>>0)Q(r,0|He.__str129,17);else{for(var We=Or+Ge|0,ie=0|He.__str129,ve=We,te=ie+17;ie>2,qe=Me[x];if((qe+26|0)>>>0>Me[Er+3]>>>0)Q(r,0|He.__str130,26);else{var $e=Or+qe|0;Pa($e,0|He.__str130,26,1);var Je=Se[x]+26|0;Se[x]=Je}var ri=Se[pr+1];H(r,ri);break r}if(17==(0|Ir)){var U=(r+8|0)>>2,ai=Me[U];if((ai+15|0)>>>0>Me[Er+3]>>>0)Q(r,0|He.__str131,15);else{for(var ei=Or+ai|0,ie=0|He.__str131,ve=ei,te=ie+15;ie>2,ti=Me[j];if((ti+19|0)>>>0>Me[Er+3]>>>0)Q(r,0|He.__str132,19);else{for(var fi=Or+ti|0,ie=0|He.__str132,ve=fi,te=ie+19;ie>2,ni=Me[X];if((ni+24|0)>>>0>Me[Er+3]>>>0)Q(r,0|He.__str133,24);else{var oi=Or+ni|0;Pa(oi,0|He.__str133,24,1);var li=Se[X]+24|0;Se[X]=li}var bi=Se[pr+1];H(r,bi);break r}if(20==(0|Ir)){var F=(r+8|0)>>2,ki=Me[F];if((ki+17|0)>>>0>Me[Er+3]>>>0)Q(r,0|He.__str134,17);else{for(var ui=Or+ki|0,ie=0|He.__str134,ve=ui,te=ie+17;ie>2,di=Me[L],wi=a+8|0,pi=Me[wi>>2];if((pi+di|0)>>>0>Me[Er+3]>>>0){var Ei=Se[pr+1];Q(r,Ei,pi);break r}var Ai=Or+di|0,gi=Se[pr+1];Pa(Ai,gi,pi,1);var yi=Se[L]+Se[wi>>2]|0;Se[L]=yi;break r}if(22==(0|Ir)||23==(0|Ir)||24==(0|Ir)){for(var mi=r+20|0;;){var mi,Si=Me[mi>>2];if(0==(0|Si))break a;if(0==(0|Se[Si+8>>2])){var Mi=Me[Se[Si+4>>2]>>2];if((Mi-22|0)>>>0>=3)break a;if((0|Mi)==(0|Ir))break}var mi=0|Si}var Ci=Se[pr+1];H(r,Ci);break r}if(25!=(0|Ir)&&26!=(0|Ir)&&27!=(0|Ir)&&28!=(0|Ir)&&29!=(0|Ir)&&30!=(0|Ir)&&31!=(0|Ir)&&32!=(0|Ir)){if(33==(0|Ir)){var D=(r+8|0)>>2,Ri=Me[D],P=(a+4|0)>>2,I=Me[P]>>2;if(0==(4&Se[Er]|0)){var Ti=Me[I+1];if((Ti+Ri|0)>>>0>Me[Er+3]>>>0){var Oi=Se[I];Q(r,Oi,Ti);break r}var Ni=Or+Ri|0,Ii=Se[I];Pa(Ni,Ii,Ti,1);var Pi=Se[D]+Se[Se[P]+4>>2]|0;Se[D]=Pi;break r}var Di=Me[I+3];if((Di+Ri|0)>>>0>Me[Er+3]>>>0){var Li=Se[I+2];Q(r,Li,Di);break r}var Fi=Or+Ri|0,Xi=Se[I+2];Pa(Fi,Xi,Di,1);var ji=Se[D]+Se[Se[P]+12>>2]|0;Se[D]=ji;break r}if(34==(0|Ir)){var Ui=Se[pr+1];H(r,Ui);break r}if(35==(0|Ir)){var N=(0|r)>>2;if(0!=(32&Se[N]|0)){var xi=Se[Er+5];rr(r,a,xi)}var zi=a+4|0,Vi=0==(0|Se[zi>>2]);e:do if(!Vi){var O=(r+20|0)>>2,Bi=Se[O],Hi=0|Mr;Se[Hi>>2]=Bi,Se[O]=Mr,Se[Mr+4>>2]=a;var Ki=Mr+8|0;Se[Ki>>2]=0;var Yi=Se[Er+4];Se[Mr+12>>2]=Yi;var Gi=Se[zi>>2];H(r,Gi);var Wi=Se[Hi>>2];if(Se[O]=Wi,0!=(0|Se[Ki>>2]))break r;if(0!=(32&Se[N]|0))break;var Zi=Me[cr],Qi=0==(0|Zi);do if(!Qi){var qi=r+8|0,$i=Me[qi>>2];if($i>>>0>=Me[Er+3]>>>0)break;Se[qi>>2]=$i+1|0,Ae[Zi+$i|0]=32;break e}while(0);Y(r,32)}while(0);if(0!=(32&Se[N]|0))break r;var Ji=Se[Er+5];rr(r,a,Ji);break r}if(36==(0|Ir)){var T=(r+20|0)>>2,rv=Me[T],av=0|Cr;Se[hr]=rv,Se[T]=av,Se[hr+1]=a;var ev=Cr+8|0;Se[ev>>2]=0;var iv=Se[Er+4];Se[hr+3]=iv;for(var vv=rv,tv=1;;){var tv,vv;if(0==(0|vv))break;if((Se[Se[vv+4>>2]>>2]-22|0)>>>0>=3)break;var fv=vv+8|0;if(0==(0|Se[fv>>2])){if(tv>>>0>3){Z(r);break r}var _v=(tv<<4)+Cr|0,R=_v>>2,C=vv>>2;Se[R]=Se[C],Se[R+1]=Se[C+1],Se[R+2]=Se[C+2],Se[R+3]=Se[C+3];var sv=Se[T];Se[_v>>2]=sv,Se[T]=_v,Se[fv>>2]=1;var nv=tv+1|0}else var nv=tv;var nv,vv=Se[vv>>2],tv=nv}var ov=Se[pr+2];if(H(r,ov),Se[T]=rv,0!=(0|Se[ev>>2]))break r;if(tv>>>0>1){for(var lv=tv;;){var lv,bv=lv-1|0,kv=Se[((bv<<4)+4>>2)+hr];if($(r,kv),bv>>>0<=1)break;var lv=bv}var uv=Se[T]}else var uv=rv;var uv;ar(r,a,uv);break r}if(37==(0|Ir)){var M=(r+20|0)>>2,cv=Se[M],hv=0|Rr;Se[hv>>2]=cv,Se[M]=Rr,Se[Rr+4>>2]=a;var dv=Rr+8|0;Se[dv>>2]=0;var wv=Se[Er+4];Se[Rr+12>>2]=wv;var pv=a+4|0,Ev=Se[pr+2];H(r,Ev);var Av=0==(0|Se[dv>>2]);e:do if(Av){var gv=Me[cr],yv=0==(0|gv);do{if(!yv){var mv=r+8|0,Sv=Me[mv>>2];if(Sv>>>0>=Me[Er+3]>>>0){gr=187;break}Se[mv>>2]=Sv+1|0,Ae[gv+Sv|0]=32,gr=188;break}gr=187}while(0);187==gr&&Y(r,32);var Mv=Se[pv>>2];H(r,Mv);var Cv=Me[cr],Rv=0==(0|Cv);do if(!Rv){var S=(r+8|0)>>2,Tv=Me[S];if((Tv+3|0)>>>0>Me[Er+3]>>>0)break;var Ov=Cv+Tv|0;Ae[Ov]=Ae[0|He.__str135],Ae[Ov+1]=Ae[(0|He.__str135)+1],Ae[Ov+2]=Ae[(0|He.__str135)+2];var Nv=Se[S]+3|0;Se[S]=Nv;break e}while(0);Q(r,0|He.__str135,3)}while(0);var Iv=Se[hv>>2];Se[M]=Iv;break r}if(38==(0|Ir)||39==(0|Ir)){var Pv=Se[pr+1];H(r,Pv);var Dv=a+8|0;if(0==(0|Se[Dv>>2]))break r;var Lv=Me[cr],Fv=0==(0|Lv);do{if(!Fv){var m=(r+8|0)>>2,Xv=Me[m];if((Xv+2|0)>>>0>Me[Er+3]>>>0){gr=197;break}var jv=Lv+Xv|0;oe=8236,Ae[jv]=255&oe,oe>>=8,Ae[jv+1]=255&oe;var Uv=Se[m]+2|0;Se[m]=Uv,gr=198;break}gr=197}while(0);197==gr&&Q(r,0|He.__str136,2);var xv=Se[Dv>>2];H(r,xv);break r}if(40==(0|Ir)){var y=(r+8|0)>>2,zv=Me[y],g=(r+12|0)>>2;if((zv+8|0)>>>0>Me[g]>>>0)Q(r,0|He.__str137,8);else{var Vv=Or+zv|0,le=0|Vv;oe=1919250543,Ae[le]=255&oe,oe>>=8,Ae[le+1]=255&oe,oe>>=8,Ae[le+2]=255&oe,oe>>=8,Ae[le+3]=255&oe;var be=Vv+4|0;oe=1919906913,Ae[be]=255&oe,oe>>=8,Ae[be+1]=255&oe,oe>>=8,Ae[be+2]=255&oe,oe>>=8,Ae[be+3]=255&oe;var Bv=Se[y]+8|0;Se[y]=Bv}var A=(a+4|0)>>2,Hv=(Ae[Se[Se[A]+4>>2]]-97&255&255)<26;e:do if(Hv){var Kv=Me[cr],Yv=0==(0|Kv);do if(!Yv){var Gv=Me[y];if(Gv>>>0>=Me[g]>>>0)break;Se[y]=Gv+1|0,Ae[Kv+Gv|0]=32;break e}while(0);Y(r,32)}while(0);var Wv=Me[cr],Zv=0==(0|Wv);do{if(!Zv){var Qv=Me[y],qv=Me[A],$v=Me[qv+8>>2];if(($v+Qv|0)>>>0>Me[g]>>>0){var Jv=qv,rt=$v;break}var at=Wv+Qv|0,et=Se[qv+4>>2];Pa(at,et,$v,1);var it=Se[y]+Se[Se[A]+8>>2]|0;Se[y]=it;break r}var vt=Me[A],Jv=vt,rt=Se[vt+8>>2]}while(0);var rt,Jv,tt=Se[Jv+4>>2];Q(r,tt,rt);break r}if(41==(0|Ir)){var E=(r+8|0)>>2,ft=Me[E];if((ft+9|0)>>>0>Me[Er+3]>>>0)Q(r,0|He.__str10180,9);else{for(var _t=Or+ft|0,ie=0|He.__str10180,ve=_t,te=ie+9;ie>2,ot=Me[p];if((ot+9|0)>>>0>Me[Er+3]>>>0)Q(r,0|He.__str10180,9);else{for(var lt=Or+ot|0,ie=0|He.__str10180,ve=lt,te=ie+9;ie>2],ct=42==(0|Se[ut>>2]);e:do if(ct){var w=(r+8|0)>>2,ht=Me[w],dt=r+12|0;ht>>>0>2]>>>0?(Se[w]=ht+1|0,Ae[Or+ht|0]=40):Y(r,40);var wt=Se[kt>>2];er(r,wt);var pt=Me[cr],Et=0==(0|pt);do if(!Et){var At=Me[w];if(At>>>0>=Me[dt>>2]>>>0)break;Se[w]=At+1|0,Ae[pt+At|0]=41;break e}while(0);Y(r,41)}else ir(r,ut);while(0);var gt=Me[cr],yt=0==(0|gt);do{if(!yt){var mt=r+8|0,St=Me[mt>>2];if(St>>>0>=Me[Er+3]>>>0){gr=232;break}Se[mt>>2]=St+1|0,Ae[gt+St|0]=40,gr=233;break}gr=232}while(0);232==gr&&Y(r,40);var Mt=Se[pr+2];H(r,Mt);var Ct=Me[cr],Rt=0==(0|Ct);do if(!Rt){var Tt=r+8|0,Ot=Me[Tt>>2];if(Ot>>>0>=Me[Er+3]>>>0)break;Se[Tt>>2]=Ot+1|0,Ae[Ct+Ot|0]=41;break r}while(0);Y(r,41);break r}if(44==(0|Ir)){var d=(a+8|0)>>2;if(45==(0|Se[Se[d]>>2])){var h=(a+4|0)>>2,Nt=Se[h],It=40==(0|Se[Nt>>2]);do if(It){var Pt=Se[Nt+4>>2];if(1!=(0|Se[Pt+8>>2]))break;if(Ae[Se[Pt+4>>2]]<<24>>24!=62)break;var Dt=r+8|0,Lt=Me[Dt>>2];Lt>>>0>>0?(Se[Dt>>2]=Lt+1|0,Ae[Or+Lt|0]=40):Y(r,40)}while(0);var Ft=Me[cr],Xt=0==(0|Ft);do{if(!Xt){var jt=r+8|0,Ut=Me[jt>>2];if(Ut>>>0>=Me[Er+3]>>>0){gr=248;break}Se[jt>>2]=Ut+1|0,Ae[Ft+Ut|0]=40,gr=249;break}gr=248}while(0);248==gr&&Y(r,40);var xt=Se[Se[d]+4>>2];H(r,xt);var zt=Me[cr],Vt=0==(0|zt);do{if(!Vt){var c=(r+8|0)>>2,Bt=Me[c];if((Bt+2|0)>>>0>Me[Er+3]>>>0){gr=252;break}var Ht=zt+Bt|0;oe=8233,Ae[Ht]=255&oe,oe>>=8,Ae[Ht+1]=255&oe;var Kt=Se[c]+2|0;Se[c]=Kt,gr=253;break}gr=252}while(0);252==gr&&Q(r,0|He.__str139,2);var Yt=Se[h];ir(r,Yt);var Gt=Me[cr],Wt=0==(0|Gt);do{if(!Wt){var u=(r+8|0)>>2,Zt=Me[u];if((Zt+2|0)>>>0>Me[Er+3]>>>0){gr=256;break}var Qt=Gt+Zt|0;oe=10272,Ae[Qt]=255&oe,oe>>=8,Ae[Qt+1]=255&oe;var qt=Se[u]+2|0;Se[u]=qt,gr=257;break}gr=256}while(0);256==gr&&Q(r,0|He.__str140,2);var $t=Se[Se[d]+8>>2];H(r,$t);var Jt=Me[cr],rf=0==(0|Jt);do{if(!rf){var af=r+8|0,ef=Me[af>>2];if(ef>>>0>=Me[Er+3]>>>0){gr=260;break}Se[af>>2]=ef+1|0,Ae[Jt+ef|0]=41,gr=261;break}gr=260}while(0);260==gr&&Y(r,41);var vf=Se[h];if(40!=(0|Se[vf>>2]))break r;var tf=Se[vf+4>>2];if(1!=(0|Se[tf+8>>2]))break r;if(Ae[Se[tf+4>>2]]<<24>>24!=62)break r;var ff=Me[cr],_f=0==(0|ff);do if(!_f){var sf=r+8|0,nf=Me[sf>>2];if(nf>>>0>=Me[Er+3]>>>0)break;Se[sf>>2]=nf+1|0,Ae[ff+nf|0]=41;break r}while(0);Y(r,41);break r}Z(r);break r}if(45==(0|Ir)){Z(r);break r}if(46==(0|Ir)){var of=a+4|0,k=(a+8|0)>>2,lf=Se[k],bf=47==(0|Se[lf>>2]);do if(bf){if(48!=(0|Se[Se[lf+8>>2]>>2]))break;var b=(r+8|0)>>2,kf=Me[b],l=(r+12|0)>>2;kf>>>0>>0?(Se[b]=kf+1|0,Ae[Or+kf|0]=40):Y(r,40);var uf=Se[Se[k]+4>>2];H(r,uf);var cf=Me[cr],hf=0==(0|cf);do{if(!hf){var df=Me[b];if((df+2|0)>>>0>Me[l]>>>0){gr=278;break}var wf=cf+df|0;oe=8233,Ae[wf]=255&oe,oe>>=8,Ae[wf+1]=255&oe;var pf=Se[b]+2|0;Se[b]=pf,gr=279;break}gr=278}while(0);278==gr&&Q(r,0|He.__str139,2);var Ef=Se[of>>2];ir(r,Ef);var Af=Me[cr],gf=0==(0|Af);do{if(!gf){var yf=Me[b];if((yf+2|0)>>>0>Me[l]>>>0){gr=282;break}var mf=Af+yf|0;oe=10272,Ae[mf]=255&oe,oe>>=8,Ae[mf+1]=255&oe;var Sf=Se[b]+2|0;Se[b]=Sf,gr=283;break}gr=282}while(0);282==gr&&Q(r,0|He.__str140,2);var Mf=Se[Se[Se[k]+8>>2]+4>>2];H(r,Mf);var Cf=Me[cr],Rf=0==(0|Cf);do{if(!Rf){var Tf=Me[b];if((Tf+5|0)>>>0>Me[l]>>>0){gr=286;break}var Of=Cf+Tf|0;Ae[Of]=Ae[0|He.__str141],Ae[Of+1]=Ae[(0|He.__str141)+1],Ae[Of+2]=Ae[(0|He.__str141)+2],Ae[Of+3]=Ae[(0|He.__str141)+3],Ae[Of+4]=Ae[(0|He.__str141)+4];var Nf=Se[b]+5|0;Se[b]=Nf,gr=287;break}gr=286}while(0);286==gr&&Q(r,0|He.__str141,5);var If=Se[Se[Se[k]+8>>2]+8>>2];H(r,If);var Pf=Me[cr],Df=0==(0|Pf);do if(!Df){var Lf=Me[b];if(Lf>>>0>=Me[l]>>>0)break;Se[b]=Lf+1|0,Ae[Pf+Lf|0]=41;break r}while(0);Y(r,41);break r}while(0);Z(r);break r}if(47==(0|Ir)||48==(0|Ir)){Z(r);break r}if(49==(0|Ir)||50==(0|Ir)){var Ff=a+4|0,Xf=Se[Ff>>2],jf=33==(0|Se[Xf>>2]);do{if(jf){var Uf=Me[Se[Xf+4>>2]+16>>2];if(1==(0|Uf)||2==(0|Uf)||3==(0|Uf)||4==(0|Uf)||5==(0|Uf)||6==(0|Uf)){var xf=a+8|0;if(0!=(0|Se[Se[xf>>2]>>2])){var zf=Uf;break}if(50==(0|Ir)){var Vf=r+8|0,Bf=Me[Vf>>2];Bf>>>0>>0?(Se[Vf>>2]=Bf+1|0,Ae[Or+Bf|0]=45):Y(r,45)}var Hf=Se[xf>>2];if(H(r,Hf),2==(0|Uf)){var Kf=Me[cr],Yf=0==(0|Kf);do if(!Yf){var Gf=r+8|0,Wf=Me[Gf>>2];if(Wf>>>0>=Me[Er+3]>>>0)break;Se[Gf>>2]=Wf+1|0,Ae[Kf+Wf|0]=117;break r}while(0);Y(r,117);break r}if(3==(0|Uf)){var Zf=Me[cr],Qf=0==(0|Zf);do if(!Qf){var qf=r+8|0,$f=Me[qf>>2];if($f>>>0>=Me[Er+3]>>>0)break;Se[qf>>2]=$f+1|0,Ae[Zf+$f|0]=108;break r}while(0);Y(r,108);break r}if(4==(0|Uf)){var Jf=Me[cr],r_=0==(0|Jf);do if(!r_){var o=(r+8|0)>>2,a_=Me[o];if((a_+2|0)>>>0>Me[Er+3]>>>0)break;var e_=Jf+a_|0;oe=27765,Ae[e_]=255&oe,oe>>=8,Ae[e_+1]=255&oe;var i_=Se[o]+2|0;Se[o]=i_;break r}while(0);Q(r,0|He.__str142,2);break r}if(5==(0|Uf)){var v_=Me[cr],t_=0==(0|v_);do if(!t_){var n=(r+8|0)>>2,f_=Me[n];if((f_+2|0)>>>0>Me[Er+3]>>>0)break;var __=v_+f_|0;oe=27756,Ae[__]=255&oe,oe>>=8,Ae[__+1]=255&oe;var s_=Se[n]+2|0;Se[n]=s_;break r}while(0);Q(r,0|He.__str143,2);break r}if(6==(0|Uf)){var n_=Me[cr],o_=0==(0|n_);do if(!o_){var s=(r+8|0)>>2,l_=Me[s];if((l_+3|0)>>>0>Me[Er+3]>>>0)break;var b_=n_+l_|0;Ae[b_]=Ae[0|He.__str144],Ae[b_+1]=Ae[(0|He.__str144)+1],Ae[b_+2]=Ae[(0|He.__str144)+2];var k_=Se[s]+3|0;Se[s]=k_;break r}while(0);Q(r,0|He.__str144,3);break r}break r}if(7==(0|Uf)){var _=Se[pr+2]>>2;if(0!=(0|Se[_])){var zf=7;break}if(!(1==(0|Se[_+2])&49==(0|Ir))){var zf=Uf;break}var u_=Ae[Se[_+1]]<<24>>24;if(48==(0|u_)){var f=(r+8|0)>>2,c_=Me[f];if((c_+5|0)>>>0>Me[Er+3]>>>0){Q(r,0|He.__str145,5);break r}var h_=Or+c_|0;Ae[h_]=Ae[0|He.__str145],Ae[h_+1]=Ae[(0|He.__str145)+1],Ae[h_+2]=Ae[(0|He.__str145)+2],Ae[h_+3]=Ae[(0|He.__str145)+3],Ae[h_+4]=Ae[(0|He.__str145)+4];var d_=Se[f]+5|0;Se[f]=d_;break r}if(49==(0|u_)){var t=(r+8|0)>>2,w_=Me[t];if((w_+4|0)>>>0>Me[Er+3]>>>0){Q(r,0|He.__str146,4);break r}var p_=Or+w_|0;oe=1702195828,Ae[p_]=255&oe,oe>>=8,Ae[p_+1]=255&oe,oe>>=8,Ae[p_+2]=255&oe,oe>>=8,Ae[p_+3]=255&oe;var E_=Se[t]+4|0;Se[t]=E_;break r}var zf=Uf;break}var zf=Uf;break}var zf=0}while(0);var zf,v=(r+8|0)>>2,A_=Me[v],i=(r+12|0)>>2;A_>>>0>>0?(Se[v]=A_+1|0,Ae[Or+A_|0]=40):Y(r,40);var g_=Se[Ff>>2];H(r,g_);var y_=Me[cr],m_=0==(0|y_);do{if(!m_){var S_=Me[v];if(S_>>>0>=Me[i]>>>0){gr=335;break}Se[v]=S_+1|0,Ae[y_+S_|0]=41,gr=336;break}gr=335}while(0);335==gr&&Y(r,41);var M_=50==(0|Se[Nr>>2]);e:do if(M_){var C_=Me[cr],R_=0==(0|C_);do if(!R_){var T_=Me[v];if(T_>>>0>=Me[i]>>>0)break;Se[v]=T_+1|0,Ae[C_+T_|0]=45;break e}while(0);Y(r,45)}while(0);if(8==(0|zf)){var O_=Me[cr],N_=0==(0|O_);do{if(!N_){var I_=Me[v];if(I_>>>0>=Me[i]>>>0){gr=345;break}Se[v]=I_+1|0,Ae[O_+I_|0]=91,gr=346;break}gr=345}while(0);345==gr&&Y(r,91);var P_=Se[pr+2];H(r,P_);var D_=Me[cr],L_=0==(0|D_);do if(!L_){var F_=Me[v];if(F_>>>0>=Me[i]>>>0)break;Se[v]=F_+1|0,Ae[D_+F_|0]=93;break r}while(0);Y(r,93);break r}var X_=Se[pr+2];H(r,X_);break r}Z(r);break r}}while(0);var e=(r+20|0)>>2,j_=Se[e],U_=0|Sr;Se[U_>>2]=j_,Se[e]=Sr,Se[Sr+4>>2]=a;var x_=Sr+8|0;Se[x_>>2]=0;var z_=Se[Er+4];Se[Sr+12>>2]=z_;var V_=Se[pr+1];H(r,V_),0==(0|Se[x_>>2])&&$(r,a);var B_=Se[U_>>2];Se[e]=B_}while(0);Oe=Ar}function K(r,a,e,i){var v=i>>2;Se[v]=r,Se[v+1]=r+e|0,Se[v+2]=a,Se[v+3]=r,Se[v+6]=e<<1,Se[v+5]=0,Se[v+9]=e,Se[v+8]=0,Se[v+10]=0,Se[v+11]=0,Se[v+12]=0}function Y(r,a){var e,i=r+4|0,v=Me[i>>2],t=0==(0|v);do if(!t){var e=(r+8|0)>>2,f=Me[e];if(f>>>0>2]>>>0)var _=v,s=f;else{tr(r,1);var n=Me[i>>2];if(0==(0|n))break;var _=n,s=Se[e]}var s,_;Ae[_+s|0]=255&a;var o=Se[e]+1|0;Se[e]=o}while(0)}function G(r,a,e,i){var v,t=i>>2,f=Oe;Oe+=4;var _=f,v=_>>2,s=0==(0|r);do if(s){if(0==(0|i)){var n=0;break}Se[t]=-3;var n=0}else{var o=0==(0|e);if(0!=(0|a)&o){if(0==(0|i)){var n=0;break}Se[t]=-3;var n=0}else{var l=W(r,_);if(0==(0|l)){if(0==(0|i)){var n=0;break}if(1==(0|Se[v])){Se[t]=-1;var n=0}else{Se[t]=-2;var n=0}}else{var b=0==(0|a);do if(b){if(o){var k=l;break}var u=Se[v];Se[e>>2]=u;var k=l}else{var c=Ca(l);if(c>>>0>2]>>>0){Ra(a,l);va(l);var k=a}else{va(a);var h=Se[v];Se[e>>2]=h;var k=l}}while(0);var k;if(0==(0|i)){var n=k;break}Se[t]=0;var n=k}}}while(0);var n;return Oe=f,n}function W(r,a){var e,i=Oe;Oe+=52;var v,t=i,e=t>>2;Se[a>>2]=0;var f=Ca(r),_=Ae[r]<<24>>24==95;do{if(_){if(Ae[r+1|0]<<24>>24==90){var s=0;v=13;break}v=3;break}v=3}while(0);do if(3==v){var n=Na(r,0|He.__str117,8);if(0!=(0|n)){var s=1;v=13;break}var o=Ae[r+8|0];if(o<<24>>24!=46&&o<<24>>24!=95&&o<<24>>24!=36){var s=1;v=13;break}var l=r+9|0,b=Ae[l];if(b<<24>>24!=68&&b<<24>>24!=73){ +var s=1;v=13;break}if(Ae[r+10|0]<<24>>24!=95){var s=1;v=13;break}var k=f+29|0,u=Jr(k);if(0==(0|u)){Se[a>>2]=1;var c=0;v=19;break}Ae[l]<<24>>24==73?Pa(u,0|He.__str118,30,1):Pa(u,0|He.__str119,29,1);var h=r+11|0,c=(Ia(u,h),u);v=19;break}while(0);if(13==v){var s;K(r,17,f,t);var d=Se[e+6],w=Ta(),p=Oe;Oe+=12*d,Oe=Oe+3>>2<<2;var E=Oe;if(Oe+=4*Se[e+9],Oe=Oe+3>>2<<2,Se[e+4]=p,Se[e+7]=E,s)var A=N(t),g=A;else var y=T(t,1),g=y;var g,m=Ae[Se[e+3]]<<24>>24==0?g:0,S=Se[e+12]+f+10*Se[e+10]|0;if(0==(0|m))var M=0;else var C=S/8+S|0,R=B(17,m,C,a),M=R;var M;Oa(w);var c=M}var c;return Oe=i,c}function Z(r){var a=r+4|0,e=Se[a>>2];va(e),Se[a>>2]=0}function Q(r,a,e){var i,v=r+4|0,t=Me[v>>2],f=0==(0|t);do if(!f){var i=(r+8|0)>>2,_=Me[i];if((_+e|0)>>>0>Me[r+12>>2]>>>0){tr(r,e);var s=Me[v>>2];if(0==(0|s))break;var n=s,o=Se[i]}else var n=t,o=_;var o,n;Pa(n+o|0,a,e,1);var l=Se[i]+e|0;Se[i]=l}while(0)}function q(r,a,e){var i,v,t=a+e|0,f=(0|e)>0;r:do if(f)for(var _=t,s=r+4|0,i=(r+8|0)>>2,n=r+12|0,o=a;;){var o,l=(_-o|0)>3;a:do{if(l){if(Ae[o]<<24>>24!=95){v=21;break}if(Ae[o+1|0]<<24>>24!=95){v=21;break}if(Ae[o+2|0]<<24>>24!=85){v=21;break}for(var b=o+3|0,k=0;;){var k,b;if(b>>>0>=t>>>0){v=21;break a}var u=ge[b],c=u<<24>>24;if((u-48&255&255)<10)var h=c-48|0;else if((u-65&255&255)<6)var h=c-55|0;else{if((u-97&255&255)>=6)break;var h=c-87|0}var h,b=b+1|0,k=(k<<4)+h|0}if(!(u<<24>>24==95&k>>>0<256)){v=21;break}var d=Me[s>>2],w=0==(0|d);do if(!w){var p=Me[i];if(p>>>0>=Me[n>>2]>>>0)break;Se[i]=p+1|0,Ae[d+p|0]=255&k;var E=b;v=25;break a}while(0);Y(r,k);var E=b;v=25;break}v=21}while(0);a:do if(21==v){var A=Me[s>>2],g=0==(0|A);do if(!g){var y=Me[i];if(y>>>0>=Me[n>>2]>>>0)break;var m=Ae[o];Se[i]=y+1|0,Ae[A+y|0]=m;var E=o;break a}while(0);var S=Ae[o]<<24>>24;Y(r,S);var E=o}while(0);var E,M=E+1|0;if(M>>>0>=t>>>0)break r;var o=M}while(0)}function $(r,a){var e,i,v,t,f,_,s,n=r>>2,o=Se[a>>2];r:do if(22==(0|o)||25==(0|o)){var l=Me[n+1],b=0==(0|l);do if(!b){var _=(r+8|0)>>2,k=Me[_];if((k+9|0)>>>0>Me[n+3]>>>0)break;for(var u=l+k|0,c=0|He.__str147,h=u,d=c+9;c>2,A=Me[f];if((A+9|0)>>>0>Me[n+3]>>>0)break;for(var g=p+A|0,c=0|He.__str148,h=g,d=c+9;c>2,M=Me[t];if((M+6|0)>>>0>Me[n+3]>>>0)break;var C=m+M|0;Ae[C]=Ae[0|He.__str149],Ae[C+1]=Ae[(0|He.__str149)+1],Ae[C+2]=Ae[(0|He.__str149)+2],Ae[C+3]=Ae[(0|He.__str149)+3],Ae[C+4]=Ae[(0|He.__str149)+4],Ae[C+5]=Ae[(0|He.__str149)+5];var R=Se[t]+6|0;Se[t]=R;break r}while(0);Q(r,0|He.__str149,6)}else if(28==(0|o)){var T=Me[n+1],O=0==(0|T);do{if(!O){var N=r+8|0,I=Me[N>>2];if(I>>>0>=Me[n+3]>>>0){s=17;break}Se[N>>2]=I+1|0,Ae[T+I|0]=32,s=18;break}s=17}while(0);17==s&&Y(r,32);var P=Se[a+8>>2];H(r,P)}else if(29==(0|o)){if(0!=(4&Se[n]|0))break;var D=Me[n+1],L=0==(0|D);do if(!L){var F=r+8|0,X=Me[F>>2];if(X>>>0>=Me[n+3]>>>0)break;Se[F>>2]=X+1|0,Ae[D+X|0]=42;break r}while(0);Y(r,42)}else if(30==(0|o)){var j=Me[n+1],U=0==(0|j);do if(!U){var x=r+8|0,z=Me[x>>2];if(z>>>0>=Me[n+3]>>>0)break;Se[x>>2]=z+1|0,Ae[j+z|0]=38;break r}while(0);Y(r,38)}else if(31==(0|o)){var V=Me[n+1],B=0==(0|V);do if(!B){var v=(r+8|0)>>2,K=Me[v];if((K+8|0)>>>0>Me[n+3]>>>0)break;var G=V+K|0,W=0|G;oe=1886220131,Ae[W]=255&oe,oe>>=8,Ae[W+1]=255&oe,oe>>=8,Ae[W+2]=255&oe,oe>>=8,Ae[W+3]=255&oe;var Z=G+4|0;oe=544761196,Ae[Z]=255&oe,oe>>=8,Ae[Z+1]=255&oe,oe>>=8,Ae[Z+2]=255&oe,oe>>=8,Ae[Z+3]=255&oe;var q=Se[v]+8|0;Se[v]=q;break r}while(0);Q(r,0|He.__str150,8)}else if(32==(0|o)){var $=Me[n+1],J=0==(0|$);do if(!J){var i=(r+8|0)>>2,rr=Me[i];if((rr+10|0)>>>0>Me[n+3]>>>0)break;for(var ar=$+rr|0,c=0|He.__str151,h=ar,d=c+10;c>2],tr=0==(0|vr);do{if(!tr){var fr=r+8|0,_r=Me[fr>>2];if(0!=(0|_r)&&Ae[vr+(_r-1)|0]<<24>>24==40){s=42;break}if(_r>>>0>=Me[n+3]>>>0){s=41;break}Se[fr>>2]=_r+1|0,Ae[vr+_r|0]=32,s=42;break}s=41}while(0);41==s&&Y(r,32);var sr=Se[a+4>>2];H(r,sr);var nr=Me[ir>>2],or=0==(0|nr);do if(!or){var e=(r+8|0)>>2,lr=Me[e];if((lr+3|0)>>>0>Me[n+3]>>>0)break;var br=nr+lr|0;Ae[br]=Ae[0|He.__str135],Ae[br+1]=Ae[(0|He.__str135)+1],Ae[br+2]=Ae[(0|He.__str135)+2];var kr=Se[e]+3|0;Se[e]=kr;break r}while(0);Q(r,0|He.__str135,3)}else if(3==(0|o)){var ur=Se[a+4>>2];H(r,ur)}else H(r,a);while(0)}function J(r){var a=r+20|0,e=Se[a>>2];if((0|e)<(0|Se[r+24>>2])){var i=Se[r+16>>2]+12*e|0,v=e+1|0;Se[a>>2]=v;var t=i}else var t=0;var t;return t}function rr(r,a,e){var i,v,t,f,_=r>>2,s=e,t=s>>2,n=0;r:for(;;){var n,s,o=0==(0|s);do if(!o){if(0!=(0|Se[t+2]))break;var l=Se[Se[t+1]>>2];if(29==(0|l)||30==(0|l)){f=9;break r}if(22==(0|l)||23==(0|l)||24==(0|l)||28==(0|l)||31==(0|l)||32==(0|l)||37==(0|l)){var b=Se[_+1];f=12;break r}var s=Se[t],t=s>>2,n=1;continue r}while(0);if(0!=(0|Se[a+4>>2])&0==(0|n)){f=9;break}var k=0,u=r+4|0,v=u>>2;f=22;break}do if(9==f){var c=Se[_+1];if(0==(0|c)){f=17;break}var h=Se[_+2];if(0==(0|h)){var d=c;f=13;break}var w=Ae[c+(h-1)|0];if(w<<24>>24==40||w<<24>>24==42){f=18;break}var b=c;f=12;break}while(0);do if(12==f){var b;if(0==(0|b)){f=17;break}var d=b;f=13;break}while(0);do if(13==f){var d,p=r+8|0,E=Me[p>>2];if(0!=(0|E)&&Ae[d+(E-1)|0]<<24>>24==32){f=18;break}if(E>>>0>=Me[_+3]>>>0){f=17;break}Se[p>>2]=E+1|0,Ae[d+E|0]=32,f=18;break}while(0);do if(17==f){Y(r,32),f=18;break}while(0);r:do if(18==f){var A=r+4|0,g=Me[A>>2],y=0==(0|g);do if(!y){var m=r+8|0,S=Me[m>>2];if(S>>>0>=Me[_+3]>>>0)break;Se[m>>2]=S+1|0,Ae[g+S|0]=40;var k=1,u=A,v=u>>2;break r}while(0);Y(r,40);var k=1,u=A,v=u>>2}while(0);var u,k,i=(r+20|0)>>2,M=Se[i];Se[i]=0,vr(r,e,0);r:do if(k){var C=Me[v],R=0==(0|C);do if(!R){var T=r+8|0,O=Me[T>>2];if(O>>>0>=Me[_+3]>>>0)break;Se[T>>2]=O+1|0,Ae[C+O|0]=41;break r}while(0);Y(r,41)}while(0);var N=Me[v],I=0==(0|N);do{if(!I){var P=r+8|0,D=Me[P>>2];if(D>>>0>=Me[_+3]>>>0){f=30;break}Se[P>>2]=D+1|0,Ae[N+D|0]=40,f=31;break}f=30}while(0);30==f&&Y(r,40);var L=Se[a+8>>2];0!=(0|L)&&H(r,L);var F=Me[v],X=0==(0|F);do{if(!X){var j=r+8|0,U=Me[j>>2];if(U>>>0>=Me[_+3]>>>0){f=36;break}Se[j>>2]=U+1|0,Ae[F+U|0]=41,f=37;break}f=36}while(0);36==f&&Y(r,41),vr(r,e,1),Se[i]=M}function ar(r,a,e){var i,v,t,f=r>>2,_=0==(0|e);do{if(!_){var s=e,v=s>>2;r:for(;;){var s;if(0==(0|s)){var n=1;t=14;break}if(0==(0|Se[v+2])){var o=36==(0|Se[Se[v+1]>>2]),l=1&o^1;if(o){var n=l;t=14;break}var b=r+4|0,k=Me[b>>2],u=0==(0|k);do{if(!u){var i=(r+8|0)>>2,c=Me[i];if((c+2|0)>>>0>Me[f+3]>>>0){t=9;break}var h=k+c|0;oe=10272,Ae[h]=255&oe,oe>>=8,Ae[h+1]=255&oe;var d=Se[i]+2|0;Se[i]=d,vr(r,e,0),t=10;break}t=9}while(0);9==t&&(Q(r,0|He.__str140,2),vr(r,e,0));var w=Me[b>>2],p=0==(0|w);do if(!p){var E=r+8|0,A=Me[E>>2];if(A>>>0>=Me[f+3]>>>0)break;Se[E>>2]=A+1|0,Ae[w+A|0]=41;var g=l;t=15;break r}while(0);Y(r,41);var g=l;t=15;break}var s=Se[v],v=s>>2}if(14==t){var n;vr(r,e,0);var g=n}var g;if(0!=(0|g)){t=17;break}var y=r+4|0;t=21;break}t=17}while(0);r:do if(17==t){var m=r+4|0,S=Me[m>>2],M=0==(0|S);do if(!M){var C=r+8|0,R=Me[C>>2];if(R>>>0>=Me[f+3]>>>0)break;Se[C>>2]=R+1|0,Ae[S+R|0]=32;var y=m;break r}while(0);Y(r,32);var y=m}while(0);var y,T=Me[y>>2],O=0==(0|T);do{if(!O){var N=r+8|0,I=Me[N>>2];if(I>>>0>=Me[f+3]>>>0){t=24;break}Se[N>>2]=I+1|0,Ae[T+I|0]=91,t=25;break}t=24}while(0);24==t&&Y(r,91);var P=Se[a+4>>2];0!=(0|P)&&H(r,P);var D=Me[y>>2],L=0==(0|D);do{if(!L){var F=r+8|0,X=Me[F>>2];if(X>>>0>=Me[f+3]>>>0){t=30;break}Se[F>>2]=X+1|0,Ae[D+X|0]=93,t=31;break}t=30}while(0);30==t&&Y(r,93)}function er(r,a){var e,i,v,t,f,_,s=Oe;Oe+=8;var n,o=s,_=(a+4|0)>>2,l=Se[_];if(4==(0|Se[l>>2])){var f=(r+20|0)>>2,b=Se[f];Se[f]=0;var t=(r+16|0)>>2,k=Se[t],u=0|o;Se[u>>2]=k,Se[t]=o;var c=Se[_];Se[o+4>>2]=c;var h=Se[c+4>>2];H(r,h);var d=Se[u>>2];Se[t]=d;var v=(r+4|0)>>2,w=Me[v],p=0==(0|w);do{if(!p){var i=(r+8|0)>>2,E=Me[i],A=0==(0|E);do if(!A){if(Ae[w+(E-1)|0]<<24>>24!=60)break;E>>>0>2]>>>0?(Se[i]=E+1|0,Ae[w+E|0]=32):Y(r,32)}while(0);var g=Me[v];if(0==(0|g)){n=12;break}var y=Me[i];if(y>>>0>=Me[r+12>>2]>>>0){n=12;break}Se[i]=y+1|0,Ae[g+y|0]=60,n=13;break}n=12}while(0);12==n&&Y(r,60);var m=Se[Se[_]+8>>2];H(r,m);var S=Me[v],M=0==(0|S);do{if(!M){var e=(r+8|0)>>2,C=Me[e],R=0==(0|C);do if(!R){if(Ae[S+(C-1)|0]<<24>>24!=62)break;C>>>0>2]>>>0?(Se[e]=C+1|0,Ae[S+C|0]=32):Y(r,32)}while(0);var T=Me[v];if(0==(0|T)){n=22;break}var O=Me[e];if(O>>>0>=Me[r+12>>2]>>>0){n=22;break}Se[e]=O+1|0,Ae[T+O|0]=62,n=23;break}n=22}while(0);22==n&&Y(r,62),Se[f]=b}else H(r,l);Oe=s}function ir(r,a){var e,i=40==(0|Se[a>>2]);r:do if(i){var v=Me[r+4>>2],t=0==(0|v);do{if(!t){var e=(r+8|0)>>2,f=Me[e],_=a+4|0,s=Me[_>>2],n=Me[s+8>>2];if((n+f|0)>>>0>Me[r+12>>2]>>>0){var o=s,l=n;break}var b=v+f|0,k=Se[s+4>>2];Pa(b,k,n,1);var u=Se[e]+Se[Se[_>>2]+8>>2]|0;Se[e]=u;break r}var c=Me[a+4>>2],o=c,l=Se[c+8>>2]}while(0);var l,o,h=Se[o+4>>2];Q(r,h,l)}else H(r,a);while(0)}function vr(r,a,e){var i,v,t,f,_,f=(r+4|0)>>2,s=0==(0|e),t=(r+16|0)>>2;r:do if(s)for(var n=a;;){var n;if(0==(0|n)){_=29;break r}if(0==(0|Se[f])){_=29;break r}var o=n+8|0,l=0==(0|Se[o>>2]);do if(l){var b=n+4|0;if((Se[Se[b>>2]>>2]-25|0)>>>0<3)break;Se[o>>2]=1;var k=Me[t],u=Se[n+12>>2];Se[t]=u;var c=Me[b>>2],h=Se[c>>2];if(35==(0|h)){var d=n,w=k,p=c;_=14;break r}if(36==(0|h)){var E=n,A=k,g=c;_=15;break r}if(2==(0|h)){var y=k,m=b;_=16;break r}$(r,c),Se[t]=k}while(0);var n=Se[n>>2]}else for(var S=a;;){var S;if(0==(0|S)){_=29;break r}if(0==(0|Se[f])){_=29;break r}var M=S+8|0;if(0==(0|Se[M>>2])){Se[M>>2]=1;var C=Me[t],R=Se[S+12>>2];Se[t]=R;var T=S+4|0,O=Me[T>>2],N=Se[O>>2];if(35==(0|N)){var d=S,w=C,p=O;_=14;break r}if(36==(0|N)){var E=S,A=C,g=O;_=15;break r}if(2==(0|N)){var y=C,m=T;_=16;break r}$(r,O),Se[t]=C}var S=Se[S>>2]}while(0);if(14==_){var p,w,d,I=Se[d>>2];rr(r,p,I),Se[t]=w}else if(15==_){var g,A,E,P=Se[E>>2];ar(r,g,P),Se[t]=A}else if(16==_){var m,y,v=(r+20|0)>>2,D=Se[v];Se[v]=0;var L=Se[Se[m>>2]+4>>2];H(r,L),Se[v]=D;var F=0==(4&Se[r>>2]|0),X=Me[f],j=0!=(0|X);r:do if(F){do if(j){var i=(r+8|0)>>2,U=Me[i];if((U+2|0)>>>0>Me[r+12>>2]>>>0)break;var x=X+U|0;oe=14906,Ae[x]=255&oe,oe>>=8,Ae[x+1]=255&oe;var z=Se[i]+2|0;Se[i]=z;break r}while(0);Q(r,0|He.__str120,2)}else{do if(j){var V=r+8|0,B=Me[V>>2];if(B>>>0>=Me[r+12>>2]>>>0)break;Se[V>>2]=B+1|0,Ae[X+B|0]=46;break r}while(0);Y(r,46)}while(0);var K=Me[Se[m>>2]+8>>2],G=(Se[K>>2]-25|0)>>>0<3;r:do if(G)for(var W=K;;){var W,Z=Me[W+4>>2];if((Se[Z>>2]-25|0)>>>0>=3){var q=Z;break r}var W=Z}else var q=K;while(0);var q;H(r,q),Se[t]=y}}function tr(r,a){var e,e=(r+4|0)>>2,i=Se[e],v=0==(0|i);r:do if(!v){for(var t=Se[r+8>>2]+a|0,f=r+12|0,_=Se[f>>2],s=i;;){var s,_;if(t>>>0<=_>>>0)break r;var n=_<<1,o=fa(s,n);if(0==(0|o))break;Se[e]=o,Se[f>>2]=n;var _=n,s=o}var l=Se[e];va(l),Se[e]=0,Se[r+24>>2]=1}while(0)}function fr(r,a,e){var i,v=J(r),i=v>>2;return 0!=(0|v)&&(Se[i]=21,Se[i+1]=a,Se[i+2]=e),v}function _r(r){var a,a=(r+12|0)>>2,e=Se[a],i=Ae[e]<<24>>24;if(88==(0|i)){var v=e+1|0;Se[a]=v;var t=nr(r),f=Se[a],_=f+1|0;Se[a]=_;var s=Ae[f]<<24>>24==69?t:0,n=s}else if(76==(0|i))var o=or(r),n=o;else var l=N(r),n=l;var n;return n}function sr(r){var a,a=(r+12|0)>>2,e=Se[a],i=Ae[e];if(i<<24>>24==110){var v=e+1|0;Se[a]=v;var t=1,f=Ae[v],_=v}else var t=0,f=i,_=e;var _,f,t,s=(f-48&255&255)<10;r:do if(s)for(var n=f,o=0,l=_;;){var l,o,n,b=(n<<24>>24)-48+10*o|0,k=l+1|0;Se[a]=k;var u=ge[k];if((u-48&255&255)>=10){var c=b;break r}var n=u,o=b,l=k}else var c=0;while(0);var c,h=0==(0|t)?c:0|-c;return h}function nr(r){var a,e,a=(r+12|0)>>2,i=Se[a],v=Ae[i];do{if(v<<24>>24==76){var t=or(r),f=t;e=21;break}if(v<<24>>24==84){var _=x(r),f=_;e=21;break}if(v<<24>>24==115){if(Ae[i+1|0]<<24>>24!=114){e=8;break}var s=i+2|0;Se[a]=s;var n=N(r),o=br(r);if(Ae[Se[a]]<<24>>24==73){var l=z(r),b=D(r,4,o,l),k=D(r,1,n,b),f=k;e=21;break}var u=D(r,1,n,o),f=u;e=21;break}e=8}while(0);r:do if(8==e){var c=kr(r);if(0==(0|c)){var f=0;break}var h=0|c,d=Se[h>>2],w=40==(0|d);do{if(w){var p=c+4|0,E=r+48|0,A=Se[Se[p>>2]+8>>2]-2+Se[E>>2]|0;Se[E>>2]=A;var g=Se[h>>2];if(40!=(0|g)){var y=g;e=13;break}var m=Se[p>>2],S=Se[m>>2],M=Da(S,0|He.__str90);if(0!=(0|M)){var C=m;e=15;break}var R=N(r),T=D(r,43,c,R),f=T;break r}var y=d;e=13}while(0);do if(13==e){var y;if(40==(0|y)){var C=Se[c+4>>2];e=15;break}if(41==(0|y)){var O=c+4|0;e=17;break}if(42==(0|y)){e=18;break}var f=0;break r}while(0);do if(15==e){var C,O=C+12|0;e=17;break}while(0);do if(17==e){var O,I=Se[O>>2];if(1==(0|I))break;if(2==(0|I)){var P=nr(r),L=nr(r),F=D(r,45,P,L),X=D(r,44,c,F);return X}if(3==(0|I)){var j=nr(r),U=nr(r),V=nr(r),B=D(r,48,U,V),H=D(r,47,j,B),K=D(r,46,c,H);return K}var f=0;break r}while(0);var Y=nr(r),G=D(r,43,c,Y);return G}while(0);var f;return f}function or(r){var a,a=(r+12|0)>>2,e=Se[a],i=e+1|0;Se[a]=i;var v=Ae[e]<<24>>24==76;r:do if(v){if(Ae[i]<<24>>24==95)var t=T(r,0),f=t;else{var _=N(r);if(0==(0|_)){var s=0;break}var n=33==(0|Se[_>>2]);do if(n){var o=Se[_+4>>2];if(0==(0|Se[o+16>>2]))break;var l=r+48|0,b=Se[l>>2]-Se[o+4>>2]|0;Se[l>>2]=b}while(0);var k=Se[a];if(Ae[k]<<24>>24==110){var u=k+1|0;Se[a]=u;var c=50,h=u}else var c=49,h=k;for(var h,c,d=h;;){var d,w=Ae[d];if(w<<24>>24==69)break;if(w<<24>>24==0){var s=0;break r}var p=d+1|0;Se[a]=p;var d=p}var E=lr(r,h,d-h|0),A=D(r,c,_,E),f=A}var f,g=Se[a],y=g+1|0;Se[a]=y;var m=Ae[g]<<24>>24==69?f:0,s=m}else var s=0;while(0);var s;return s}function lr(r,a,e){var i=J(r),v=m(i,a,e),t=0==(0|v)?0:i;return t}function br(r){var a=r+12|0,e=Me[a>>2],i=ge[e],v=(i-48&255&255)<10;do if(v)var t=L(r),f=t;else if((i-97&255&255)<26){var _=kr(r);if(0==(0|_)){var f=0;break}if(40!=(0|Se[_>>2])){var f=_;break}var s=r+48|0,n=Se[Se[_+4>>2]+8>>2]+Se[s>>2]+7|0;Se[s>>2]=n;var f=_}else if(i<<24>>24==67||i<<24>>24==68)var o=hr(r),f=o;else{if(i<<24>>24!=76){var f=0;break}Se[a>>2]=e+1|0;var l=L(r);if(0==(0|l)){var f=0;break}var b=dr(r),k=0==(0|b)?0:l,f=k}while(0);var f;return f}function kr(r){var a,e,a=(r+12|0)>>2,i=Se[a],v=i+1|0;Se[a]=v;var t=ge[i],f=i+2|0;Se[a]=f;var _=ge[v];do{if(t<<24>>24==118){if((_-48&255&255)>=10){var s=49,n=0;e=6;break}var o=(_<<24>>24)-48|0,l=L(r),b=ur(r,o,l),k=b;e=14;break}if(t<<24>>24==99){if(_<<24>>24!=118){var s=49,n=0;e=6;break}var u=N(r),c=D(r,42,u,0),k=c;e=14;break}var s=49,n=0;e=6}while(0);r:do if(6==e){for(;;){var n,s,h=(s-n)/2+n|0,d=(h<<4)+ri|0,w=Se[d>>2],p=Ae[w],E=t<<24>>24==p<<24>>24;if(E&&_<<24>>24==Ae[w+1|0]<<24>>24)break;var A=t<<24>>24>24;do if(A)var g=h,y=n;else{if(E&&_<<24>>24>24){var g=h,y=n;break}var g=s,y=h+1|0}while(0);var y,g;if((0|y)==(0|g)){var k=0;break r}var s=g,n=y}var m=cr(r,d),k=m}while(0);var k;return k}function ur(r,a,e){var i=J(r),v=S(i,a,e),t=0==(0|v)?0:i;return t}function cr(r,a){var e=J(r);return 0!=(0|e)&&(Se[e>>2]=40,Se[e+4>>2]=a),e}function hr(r){var a,e,i=Se[r+44>>2],e=i>>2,v=0==(0|i);do if(!v){var t=Se[e];if(0==(0|t)){var f=r+48|0,_=Se[f>>2]+Se[e+2]|0;Se[f>>2]=_}else{if(21!=(0|t))break;var s=r+48|0,n=Se[s>>2]+Se[e+2]|0;Se[s>>2]=n}}while(0);var a=(r+12|0)>>2,o=Se[a],l=o+1|0;Se[a]=l;var b=Ae[o]<<24>>24;do if(67==(0|b)){var k=o+2|0;Se[a]=k;var u=Ae[l]<<24>>24;if(49==(0|u))var c=1;else if(50==(0|u))var c=2;else{if(51!=(0|u)){var h=0;break}var c=3}var c,d=wr(r,c,i),h=d}else if(68==(0|b)){var w=o+2|0;Se[a]=w;var p=Ae[l]<<24>>24;if(48==(0|p))var E=1;else if(49==(0|p))var E=2;else{if(50!=(0|p)){var h=0;break}var E=3}var E,A=pr(r,E,i),h=A}else var h=0;while(0);var h;return h}function dr(r){var a=r+12|0,e=Se[a>>2];if(Ae[e]<<24>>24==95){var i=e+1|0;Se[a>>2]=i;var v=sr(r),t=v>>>31^1}else var t=1;var t;return t}function wr(r,a,e){var i=J(r),v=M(i,a,e),t=0==(0|v)?0:i;return t}function pr(r,a,e){var i=J(r),v=C(i,a,e),t=0==(0|v)?0:i;return t}function Er(r,a){var e=J(r);return 0!=(0|e)&&(Se[e>>2]=5,Se[e+4>>2]=a),e}function Ar(r){var a,a=(r+12|0)>>2,e=Se[a],i=Ae[e]<<24>>24;do if(78==(0|i))var v=gr(r),t=v;else if(90==(0|i))var f=yr(r),t=f;else if(76==(0|i))var _=br(r),t=_;else if(83==(0|i)){if(Ae[e+1|0]<<24>>24==116){var s=e+2|0;Se[a]=s;var n=lr(r,0|He.__str152,3),o=br(r),l=D(r,1,n,o),b=r+48|0,k=Se[b>>2]+3|0;Se[b>>2]=k;var u=0,c=l}else var h=V(r,0),u=1,c=h;var c,u;if(Ae[Se[a]]<<24>>24!=73){var t=c;break}if(0==(0|u)){var d=R(r,c);if(0==(0|d)){var t=0;break}}var w=z(r),p=D(r,4,c,w),t=p}else{var E=br(r);if(Ae[Se[a]]<<24>>24!=73){var t=E;break}var A=R(r,E);if(0==(0|A)){var t=0;break}var g=z(r),y=D(r,4,E,g),t=y}while(0);var t;return t}function gr(r){var a,e=Oe;Oe+=4;var i=e,a=(r+12|0)>>2,v=Se[a],t=v+1|0;Se[a]=t;var f=Ae[v]<<24>>24==78;do if(f){var _=I(r,i,1);if(0==(0|_)){var s=0;break}var n=mr(r);if(Se[_>>2]=n,0==(0|n)){var s=0;break}var o=Se[a],l=o+1|0;if(Se[a]=l,Ae[o]<<24>>24!=69){var s=0;break}var s=Se[i>>2]}else var s=0;while(0);var s;return Oe=e,s}function yr(r){var a,a=(r+12|0)>>2,e=Se[a],i=e+1|0;Se[a]=i;var v=Ae[e]<<24>>24==90;do if(v){var t=O(r,0),f=Se[a],_=f+1|0;if(Se[a]=_,Ae[f]<<24>>24!=69){var s=0;break}if(Ae[_]<<24>>24==115){var n=f+2|0;Se[a]=n;var o=dr(r);if(0==(0|o)){var s=0;break}var l=lr(r,0|He.__str168,14),b=D(r,2,t,l),s=b}else{var k=Ar(r),u=dr(r);if(0==(0|u)){var s=0;break}var c=D(r,2,t,k),s=c}}else var s=0;while(0);var s;return s}function mr(r){var a,e=r+12|0,i=0;r:for(;;){var i,v=ge[Se[e>>2]];if(v<<24>>24==0){var t=0;break}var f=(v-48&255&255)<10|(v-97&255&255)<26;do{if(!f){if(v<<24>>24==76||v<<24>>24==68||v<<24>>24==67){a=5;break}if(v<<24>>24==83){var _=V(r,1),s=_;a=10;break}if(v<<24>>24==73){if(0==(0|i)){var t=0;break r}var n=z(r),o=4,l=n;a=11;break}if(v<<24>>24==84){var b=x(r),s=b;a=10;break}if(v<<24>>24==69){var t=i;break r}var t=0;break r}a=5}while(0);do if(5==a){var k=br(r),s=k;a=10;break}while(0);do if(10==a){var s;if(0==(0|i)){var u=s;a=12;break}var o=1,l=s;a=11;break}while(0);if(11==a)var l,o,c=D(r,o,i,l),u=c;var u;if(v<<24>>24!=83)if(Ae[Se[e>>2]]<<24>>24!=69){var h=R(r,u);if(0==(0|h)){var t=0;break}var i=u}else var i=u;else var i=u}var t;return t}function Sr(r,a){var e,i,v=Oe;Oe+=4;var t=v,i=t>>2,e=(r+12|0)>>2,f=Se[e];if(Ae[f]<<24>>24==74){var _=f+1|0;Se[e]=_;var s=1}else var s=a;var s;Se[i]=0;var n=s,o=0,l=t;r:for(;;)for(var l,o,n,b=n,k=o;;){var k,b,u=Ae[Se[e]];if(u<<24>>24==0||u<<24>>24==69){var c=Se[i];if(0==(0|c)){var h=0;break r}var d=0==(0|Se[c+8>>2]);do if(d){var w=Se[c+4>>2];if(33!=(0|Se[w>>2])){var p=c;break}var E=Se[w+4>>2];if(9!=(0|Se[E+16>>2])){var p=c;break}var A=r+48|0,g=Se[A>>2]-Se[E+4>>2]|0;Se[A>>2]=g,Se[i]=0;var p=0}else var p=c;while(0);var p,y=D(r,35,k,p),h=y;break r}var m=N(r);if(0==(0|m)){var h=0;break r}if(0==(0|b)){var S=D(r,38,m,0);if(Se[l>>2]=S,0==(0|S)){var h=0;break r}var n=0,o=k,l=S+8|0;continue r}var b=0,k=m}var h;return Oe=v,h}function Mr(r){for(var a=r;;){var a;if(0==(0|a)){var e=0;break}var i=Se[a>>2];if(1!=(0|i)&&2!=(0|i)){if(6==(0|i)||7==(0|i)||42==(0|i)){var e=1;break}var e=0;break}var a=Se[a+8>>2]}var e;return e}function Cr(r){var a=r>>2;Se[a+3]=0,Se[a+2]=0,Se[a+1]=0,Se[a]=0,Se[a+4]=0}function Rr(r,a){var e,e=(r+12|0)>>2,i=Se[e],v=(Se[r+4>>2]-i|0)<(0|a);r:do if(v)var t=0;else{var f=i+a|0;Se[e]=f;var _=0==(4&Se[r+8>>2]|0);do if(!_){if(Ae[f]<<24>>24!=36)break;var s=a+(i+1)|0;Se[e]=s}while(0);var n=(0|a)>9;do if(n){var o=La(i,0|He.__str117,8);if(0!=(0|o))break;var l=Ae[i+8|0];if(l<<24>>24!=46&&l<<24>>24!=95&&l<<24>>24!=36)break;if(Ae[i+9|0]<<24>>24!=78)break;var b=r+48|0,k=22-a+Se[b>>2]|0;Se[b>>2]=k;var u=lr(r,0|He.__str169,21),t=u;break r}while(0);var c=lr(r,i,a),t=c}while(0);var t;return t}function Tr(r){var a,e,e=(r+48|0)>>2,i=Se[e],v=i+20|0;Se[e]=v;var a=(r+12|0)>>2,t=Se[a],f=t+1|0;Se[a]=f;var _=Ae[t];do if(_<<24>>24==84){var s=t+2|0;Se[a]=s;var n=Ae[f]<<24>>24;if(86==(0|n)){var o=i+15|0;Se[e]=o;var l=N(r),b=D(r,8,l,0),k=b}else if(84==(0|n)){var u=i+10|0;Se[e]=u;var c=N(r),h=D(r,9,c,0),k=h}else if(73==(0|n))var d=N(r),w=D(r,11,d,0),k=w;else if(83==(0|n))var p=N(r),E=D(r,12,p,0),k=E;else if(104==(0|n)){var A=Nr(r,104);if(0==(0|A)){var k=0;break}var g=O(r,0),y=D(r,14,g,0),k=y}else if(118==(0|n)){var m=Nr(r,118);if(0==(0|m)){var k=0;break}var S=O(r,0),M=D(r,15,S,0),k=M}else if(99==(0|n)){var C=Nr(r,0);if(0==(0|C)){var k=0;break}var R=Nr(r,0);if(0==(0|R)){var k=0;break}var T=O(r,0),I=D(r,16,T,0),k=I}else if(67==(0|n)){var P=N(r),L=sr(r);if((0|L)<0){var k=0;break}var F=Se[a],X=F+1|0;if(Se[a]=X,Ae[F]<<24>>24!=95){var k=0;break}var j=N(r),U=Se[e]+5|0;Se[e]=U;var x=D(r,10,j,P),k=x}else if(70==(0|n))var z=N(r),V=D(r,13,z,0),k=V;else{if(74!=(0|n)){var k=0;break}var B=N(r),H=D(r,17,B,0),k=H}}else if(_<<24>>24==71){var K=t+2|0;Se[a]=K;var Y=Ae[f]<<24>>24;if(86==(0|Y))var G=Ar(r),W=D(r,18,G,0),k=W;else if(82==(0|Y))var Z=Ar(r),Q=D(r,19,Z,0),k=Q;else{if(65!=(0|Y)){var k=0;break}var q=O(r,0),$=D(r,20,q,0),k=$}}else var k=0;while(0);var k;return k}function Or(r){for(var a,e=r,a=e>>2;;){var e;if(0==(0|e)){var i=0;break}var v=Se[a];if(4==(0|v)){var t=Se[a+1],f=Mr(t),i=0==(0|f)&1;break}if(25!=(0|v)&&26!=(0|v)&&27!=(0|v)){var i=0;break}var e=Se[a+1],a=e>>2}var i;return i}function Nr(r,a){var e;if(0==(0|a)){var i=r+12|0,v=Se[i>>2],t=v+1|0;Se[i>>2]=t;var f=Ae[v]<<24>>24}else var f=a;var f;do{if(104==(0|f)){var _=(sr(r),r+12|0);e=7;break}if(118==(0|f)){var s=(sr(r),r+12|0),n=Se[s>>2],o=n+1|0;if(Se[s>>2]=o,Ae[n]<<24>>24!=95){var l=0;e=8;break}var _=(sr(r),s);e=7;break}var l=0;e=8}while(0);if(7==e){var _,b=Se[_>>2],k=b+1|0;Se[_>>2]=k;var l=Ae[b]<<24>>24==95&1}var l;return l}function Ir(r){var a,e,i=r>>2,v=Oe;Oe+=56;var t,f=v,_=v+8,s=v+16,n=v+36,e=(0|r)>>2,o=Se[e],l=0==(8192&o|0);r:do{if(l){var a=(r+12|0)>>2,b=Se[a];if(Ae[b]<<24>>24!=63){var k=0;t=111;break}var u=b+1|0;Se[a]=u;var c=Ae[u];do if(c<<24>>24==63){if(Ae[b+2|0]<<24>>24==36){var h=b+3|0;if(Ae[h]<<24>>24!=63){var d=5;t=90;break}Se[a]=h;var w=6,p=h}else var w=0,p=u;var p,w,E=p+1|0;Se[a]=E;var A=Ae[E]<<24>>24;do if(48==(0|A)){var g=1;t=81}else{if(49==(0|A)){var g=2;t=81;break}if(50!=(0|A)){if(51==(0|A)){var y=0|He.__str2172,m=E;t=82;break}if(52==(0|A)){var y=0|He.__str3173,m=E;t=82;break}if(53==(0|A)){var y=0|He.__str4174,m=E;t=82;break}if(54==(0|A)){var y=0|He.__str5175,m=E;t=82;break}if(55==(0|A)){var y=0|He.__str6176,m=E;t=82;break}if(56==(0|A)){var y=0|He.__str7177,m=E;t=82;break}if(57==(0|A)){var y=0|He.__str8178,m=E;t=82;break}if(65==(0|A)){var y=0|He.__str9179,m=E;t=82;break}if(66==(0|A)){Se[a]=p+2|0;var S=0|He.__str10180,M=3;t=88;break}if(67==(0|A)){var y=0|He.__str11181,m=E;t=82;break}if(68==(0|A)){var y=0|He.__str12182,m=E;t=82;break}if(69==(0|A)){var y=0|He.__str13183,m=E;t=82;break}if(70==(0|A)){var y=0|He.__str14184,m=E;t=82;break}if(71==(0|A)){var y=0|He.__str15185,m=E;t=82;break}if(72==(0|A)){var y=0|He.__str16186,m=E;t=82;break}if(73==(0|A)){var y=0|He.__str17187,m=E;t=82;break}if(74==(0|A)){var y=0|He.__str18188,m=E;t=82;break}if(75==(0|A)){var y=0|He.__str19189,m=E;t=82;break}if(76==(0|A)){var y=0|He.__str20190,m=E;t=82;break}if(77==(0|A)){var y=0|He.__str21191,m=E;t=82;break}if(78==(0|A)){var y=0|He.__str22192,m=E;t=82;break}if(79==(0|A)){var y=0|He.__str23193,m=E;t=82;break}if(80==(0|A)){var y=0|He.__str24194,m=E;t=82;break}if(81==(0|A)){var y=0|He.__str25195,m=E;t=82;break}if(82==(0|A)){var y=0|He.__str26196,m=E;t=82;break}if(83==(0|A)){var y=0|He.__str27197,m=E;t=82;break}if(84==(0|A)){var y=0|He.__str28198,m=E;t=82;break}if(85==(0|A)){var y=0|He.__str29199,m=E;t=82;break}if(86==(0|A)){var y=0|He.__str30200,m=E;t=82;break}if(87==(0|A)){var y=0|He.__str31201,m=E;t=82;break}if(88==(0|A)){var y=0|He.__str32202,m=E;t=82;break}if(89==(0|A)){var y=0|He.__str33203,m=E;t=82;break}if(90==(0|A)){var y=0|He.__str34204,m=E;t=82;break}if(95==(0|A)){var C=p+2|0;Se[a]=C;var R=Ae[C]<<24>>24;if(48==(0|R)){var y=0|He.__str35205,m=C;t=82;break}if(49==(0|R)){var y=0|He.__str36206,m=C;t=82;break}if(50==(0|R)){var y=0|He.__str37207,m=C;t=82;break}if(51==(0|R)){var y=0|He.__str38208,m=C;t=82;break}if(52==(0|R)){var y=0|He.__str39209,m=C;t=82;break}if(53==(0|R)){var y=0|He.__str40210,m=C;t=82;break}if(54==(0|R)){var y=0|He.__str41211,m=C;t=82;break}if(55==(0|R)){var y=0|He.__str42212,m=C;t=82;break}if(56==(0|R)){var y=0|He.__str43213,m=C;t=82;break}if(57==(0|R)){var y=0|He.__str44214,m=C;t=82;break}if(65==(0|R)){var y=0|He.__str45215,m=C;t=82;break}if(66==(0|R)){var y=0|He.__str46216,m=C;t=82;break}if(67==(0|R)){Se[a]=p+3|0;var T=0|He.__str47217;t=84;break}if(68==(0|R)){var y=0|He.__str48218,m=C;t=82;break}if(69==(0|R)){var y=0|He.__str49219,m=C;t=82;break}if(70==(0|R)){var y=0|He.__str50220,m=C;t=82;break}if(71==(0|R)){var y=0|He.__str51221,m=C;t=82;break}if(72==(0|R)){var y=0|He.__str52222,m=C;t=82;break}if(73==(0|R)){var y=0|He.__str53223,m=C;t=82;break}if(74==(0|R)){var y=0|He.__str54224,m=C;t=82;break}if(75==(0|R)){var y=0|He.__str55225,m=C;t=82;break}if(76==(0|R)){var y=0|He.__str56226,m=C;t=82;break}if(77==(0|R)){var y=0|He.__str57227,m=C;t=82;break}if(78==(0|R)){var y=0|He.__str58228,m=C;t=82;break}if(79==(0|R)){var y=0|He.__str59229,m=C;t=82;break}if(82==(0|R)){var O=4|o;Se[e]=O;var N=p+3|0;Se[a]=N;var I=Ae[N]<<24>>24;if(48==(0|I)){Se[a]=p+4|0,Cr(s);var P=(Pr(r,_,s,0),Se[_>>2]),D=Se[_+4>>2],L=Dr(r,0|He.__str60230,(ne=Oe,Oe+=8,Se[ne>>2]=P,Se[ne+4>>2]=D,ne)),F=Se[a]-1|0;Se[a]=F;var y=L,m=F;t=82;break}if(49==(0|I)){Se[a]=p+4|0;var X=Lr(r),j=Lr(r),U=Lr(r),x=Lr(r),z=Se[a]-1|0;Se[a]=z;var V=Dr(r,0|He.__str61231,(ne=Oe,Oe+=16,Se[ne>>2]=X,Se[ne+4>>2]=j,Se[ne+8>>2]=U,Se[ne+12>>2]=x,ne)),y=V,m=Se[a];t=82;break}if(50==(0|I)){var y=0|He.__str62232,m=N;t=82;break}if(51==(0|I)){var y=0|He.__str63233,m=N;t=82;break}if(52==(0|I)){var y=0|He.__str64234,m=N;t=82;break}var y=0,m=N;t=82;break}if(83==(0|R)){var y=0|He.__str65235,m=C;t=82;break}if(84==(0|R)){var y=0|He.__str66236,m=C;t=82;break}if(85==(0|R)){var y=0|He.__str67237,m=C;t=82;break}if(86==(0|R)){var y=0|He.__str68238,m=C;t=82;break}if(88==(0|R)){var y=0|He.__str69239,m=C;t=82;break}if(89==(0|R)){var y=0|He.__str70240,m=C;t=82;break}var k=0;t=111;break r}var k=0;t=111;break r}var y=0|He.__str1171,m=E;t=82}while(0);do{if(81==t){var g;Se[a]=p+2|0;var B=g;t=83;break}if(82==t){var m,y;if(Se[a]=m+1|0,1==(0|w)||2==(0|w)){var B=w;t=83;break}if(4==(0|w)){var T=y;t=84;break}if(6!=(0|w)){var S=y,M=w;t=88;break}Cr(n);var H=Xr(r,n,0,60,62);if(0==(0|H))var K=y;else var Y=Dr(r,0|He.__str170,(ne=Oe,Oe+=8,Se[ne>>2]=y,Se[ne+4>>2]=H,ne)),K=Y;var K;Se[i+6]=0;var S=K,M=w;t=88;break}}while(0);if(83==t){var B,G=r+40|0,W=Fr(r,0|He._symbol_demangle_dashed_null,-1,G);if(0==(0|W)){var k=0;t=111;break r}var d=B;t=90;break}if(84==t){var T;Se[i+4]=T;var Z=1,Q=T;t=109;break r}if(88==t){var M,S,q=r+40|0,$=Fr(r,S,-1,q);if(0==(0|$)){var k=0;t=111;break r}var d=M;t=90;break}}else{if(c<<24>>24==36){var J=b+2|0;Se[a]=J;var rr=jr(r);Se[i+4]=rr;var ar=0!=(0|rr)&1;t=107;break}var d=0;t=90}while(0);if(90==t){var d,er=Me[a],ir=Ae[er]<<24>>24;if(64==(0|ir))Se[a]=er+1|0;else if(36==(0|ir))t=93;else{var vr=zr(r);if(0==(0|vr)){var k=-1;t=111;break}}if(5==(0|d)){var tr=r+20|0,fr=Se[tr>>2]+1|0;Se[tr>>2]=fr}else if(1==(0|d)||2==(0|d)){if(Me[i+11]>>>0<2){var k=-1;t=111;break}var _r=r+56|0,sr=Me[_r>>2],nr=Se[sr+4>>2];if(1==(0|d))Se[sr>>2]=nr;else{var or=Dr(r,0|He.__str71241,(ne=Oe,Oe+=4,Se[ne>>2]=nr,ne)),lr=Se[_r>>2];Se[lr>>2]=or}var br=4|Se[e];Se[e]=br}else if(3==(0|d)){var kr=Se[e]&-5;Se[e]=kr}var ur=ge[Se[a]];if((ur-48&255&255)<10)var cr=Vr(r),ar=cr;else if((ur-65&255&255)<26)var hr=Br(r,3==(0|d)&1),ar=hr;else{if(ur<<24>>24!=36){var k=-1;t=111;break}var dr=Hr(r),ar=dr}}var ar;if(0==(0|ar)){var k=-1;t=111;break}var Z=ar,Q=Se[i+4];t=109;break}var wr=Pr(r,f,0,0);if(0==(0|wr)){var k=-1;t=111;break}var pr=Se[f>>2],Er=Se[f+4>>2],Ar=Dr(r,0|He.__str170,(ne=Oe,Oe+=8,Se[ne>>2]=pr,Se[ne+4>>2]=Er,ne));Se[i+4]=Ar;var Z=1,Q=Ar;t=109;break}while(0);do if(109==t){var Q,Z;if(0!=(0|Q)){var k=Z;break}Xa(0|He.__str72242,1499,0|He.___func___symbol_demangle,0|He.__str73243);var k=Z}while(0);var k;return Oe=v,k}function Pr(r,a,e,i){var v,t,f,_=Oe;Oe+=24;var s=_,n=_+4,o=_+8,l=_+16,b=_+20;0==(0|a)&&Xa(0|He.__str72242,829,0|He.___func___demangle_datatype,0|He.__str121291);var f=(a+4|0)>>2;Se[f]=0;var t=(0|a)>>2;Se[t]=0;var v=(r+12|0)>>2,k=Me[v],u=k+1|0;Se[v]=u;var c=Ae[k],h=c<<24>>24;do if(95==(0|h)){Se[v]=k+2|0;var d=Ae[u],w=Zr(d);Se[t]=w}else if(67==(0|h)||68==(0|h)||69==(0|h)||70==(0|h)||71==(0|h)||72==(0|h)||73==(0|h)||74==(0|h)||75==(0|h)||77==(0|h)||78==(0|h)||79==(0|h)||88==(0|h)||90==(0|h)){var p=Qr(c);Se[t]=p}else if(84==(0|h)||85==(0|h)||86==(0|h)||89==(0|h)){var E=qr(r);if(0==(0|E))break;var A=0==(32768&Se[r>>2]|0);do if(A)if(84==(0|h))var g=0|He.__str122292;else if(85==(0|h))var g=0|He.__str123293;else if(86==(0|h))var g=0|He.__str124294;else{if(89!=(0|h)){var g=0;break}var g=0|He.__str125295}else var g=0;while(0);var g,y=Dr(r,0|He.__str170,(ne=Oe,Oe+=8,Se[ne>>2]=g,Se[ne+4>>2]=E,ne));Se[t]=y}else if(63==(0|h))if(0==(0|i))$r(a,r,e,63,0);else{var m=Lr(r);if(0==(0|m))break;var S=Dr(r,0|He.__str126296,(ne=Oe,Oe+=4,Se[ne>>2]=m,ne));Se[t]=S}else if(65==(0|h)||66==(0|h))$r(a,r,e,c,i);else if(81==(0|h)||82==(0|h)||83==(0|h)){var M=0==(0|i)?80:c;$r(a,r,e,M,i)}else if(80==(0|h))if(((Ae[u]<<24>>24)-48|0)>>>0<10){var C=k+2|0;if(Se[v]=C,Ae[u]<<24>>24!=54)break;var R=r+44|0,T=Se[R>>2];Se[v]=k+3|0;var O=Ae[C],N=Se[r>>2]&-17,I=Ur(O,s,n,N);if(0==(0|I))break;var P=Pr(r,o,e,0);if(0==(0|P))break;var D=Xr(r,e,1,40,41);if(0==(0|D))break;Se[R>>2]=T;var L=Se[o>>2],F=Se[o+4>>2],X=Se[s>>2],j=Dr(r,0|He.__str127297,(ne=Oe,Oe+=12,Se[ne>>2]=L,Se[ne+4>>2]=F,Se[ne+8>>2]=X,ne));Se[t]=j;var U=Dr(r,0|He.__str128298,(ne=Oe,Oe+=4,Se[ne>>2]=D,ne));Se[f]=U}else $r(a,r,e,80,i);else if(87==(0|h)){if(Ae[u]<<24>>24!=52)break;Se[v]=k+2|0;var x=qr(r);if(0==(0|x))break;if(0==(32768&Se[r>>2]|0)){var z=Dr(r,0|He.__str129299,(ne=Oe,Oe+=4,Se[ne>>2]=x,ne));Se[t]=z}else Se[t]=x}else if(48==(0|h)||49==(0|h)||50==(0|h)||51==(0|h)||52==(0|h)||53==(0|h)||54==(0|h)||55==(0|h)||56==(0|h)||57==(0|h)){var V=h<<1,B=V-96|0,H=Yr(e,B);Se[t]=H;var K=V-95|0,Y=Yr(e,K);Se[f]=Y}else if(36==(0|h)){var G=k+2|0;Se[v]=G;var W=Ae[u]<<24>>24;if(48==(0|W)){var Z=Lr(r);Se[t]=Z}else if(68==(0|W)){var Q=Lr(r);if(0==(0|Q))break;var q=Dr(r,0|He.__str130300,(ne=Oe,Oe+=4,Se[ne>>2]=Q,ne));Se[t]=q}else if(70==(0|W)){var $=Lr(r);if(0==(0|$))break;var J=Lr(r);if(0==(0|J))break;var rr=Dr(r,0|He.__str131301,(ne=Oe,Oe+=8,Se[ne>>2]=$,Se[ne+4>>2]=J,ne));Se[t]=rr}else if(71==(0|W)){var ar=Lr(r);if(0==(0|ar))break;var er=Lr(r);if(0==(0|er))break;var ir=Lr(r);if(0==(0|ir))break;var vr=Dr(r,0|He.__str132302,(ne=Oe,Oe+=12,Se[ne>>2]=ar,Se[ne+4>>2]=er,Se[ne+8>>2]=ir,ne));Se[t]=vr}else if(81==(0|W)){var tr=Lr(r);if(0==(0|tr))break;var fr=Dr(r,0|He.__str133303,(ne=Oe,Oe+=4,Se[ne>>2]=tr,ne));Se[t]=fr}else{if(36!=(0|W))break;if(Ae[G]<<24>>24!=67)break;Se[v]=k+3|0;var _r=xr(r,l,b);if(0==(0|_r))break;var sr=Pr(r,a,e,i);if(0==(0|sr))break;var nr=Se[t],or=Se[l>>2],lr=Dr(r,0|He.__str83253,(ne=Oe,Oe+=8,Se[ne>>2]=nr,Se[ne+4>>2]=or,ne));Se[t]=lr}}while(0);var br=0!=(0|Se[t])&1;return Oe=_,br}function Dr(r,a){var e,i=Oe;Oe+=4;var v=i,e=v>>2,t=v;Se[t>>2]=arguments[Dr.length];var f=1,_=0;r:for(;;){var _,f,s=Ae[a+_|0];do{if(s<<24>>24==0)break r;if(s<<24>>24==37){var n=_+1|0,o=Ae[a+n|0]<<24>>24;if(115==(0|o)){var l=Se[e],b=l,k=l+4|0;Se[e]=k;var u=Se[b>>2];if(0==(0|u)){var c=f,h=n;break}var d=Ca(u),c=d+f|0,h=n;break}if(99==(0|o)){var w=Se[e]+4|0;Se[e]=w;var c=f+1|0,h=n;break}if(37==(0|o))var p=n;else var p=_;var p,c=f+1|0,h=p}else var c=f+1|0,h=_}while(0);var h,c,f=c,_=h+1|0}var E=Wr(r,f);if(0==(0|E))var A=0;else{Se[t>>2]=arguments[Dr.length];var g=E,y=0;r:for(;;){var y,g,m=Ae[a+y|0];do{if(m<<24>>24==0)break r;if(m<<24>>24==37){var S=y+1|0,M=Ae[a+S|0]<<24>>24;if(115==(0|M)){var C=Se[e],R=C,T=C+4|0;Se[e]=T;var O=Se[R>>2];if(0==(0|O)){var N=g,I=S;break}var P=Ca(O);Pa(g,O,P,1);var N=g+P|0,I=S;break}if(99==(0|M)){var D=Se[e],L=D,F=D+4|0;Se[e]=F,Ae[g]=255&Se[L>>2];var N=g+1|0,I=S;break}if(37==(0|M))var X=S;else var X=y;var X;Ae[g]=37;var N=g+1|0,I=X}else{Ae[g]=m;var N=g+1|0,I=y}}while(0);var I,N,g=N,y=I+1|0}Ae[g]=0;var A=E}var A;return Oe=i,A}function Lr(r){var a,a=(r+12|0)>>2,e=Se[a],i=Ae[e];if(i<<24>>24==63){var v=e+1|0;Se[a]=v;var t=1,f=v,_=Ae[v]}else var t=0,f=e,_=i;var _,f,t,s=(_-48&255&255)<9;do if(s){var n=Wr(r,3),o=0!=(0|t);o&&(Ae[n]=45);var l=Ae[Se[a]]+1&255;Ae[n+t|0]=l;var b=o?2:1; +Ae[n+b|0]=0;var k=Se[a]+1|0;Se[a]=k;var u=n}else if(_<<24>>24==57){var c=Wr(r,4),h=0!=(0|t);h&&(Ae[c]=45),Ae[c+t|0]=49;var d=h?2:1;Ae[c+d|0]=48;var w=h?3:2;Ae[c+w|0]=0;var p=Se[a]+1|0;Se[a]=p;var u=c}else{if((_-65&255&255)>=16){var u=0;break}for(var E=0,A=f;;){var A,E,g=A+1|0;Se[a]=g;var y=(Ae[A]<<24>>24)+((E<<4)-65)|0,m=ge[g];if((m-65&255&255)>=16)break;var E=y,A=g}if(m<<24>>24!=64){var u=0;break}var S=Wr(r,17),M=0!=(0|t)?0|He.__str119289:0|ii,C=(za(S,0|He.__str118288,(ne=Oe,Oe+=8,Se[ne>>2]=M,Se[ne+4>>2]=y,ne)),Se[a]+1|0);Se[a]=C;var u=S}while(0);var u;return u}function Fr(r,a,e,i){var v,t,f,_;0==(0|a)&&Xa(0|He.__str72242,212,0|He.___func___str_array_push,0|He.__str115285),0==(0|i)&&Xa(0|He.__str72242,213,0|He.___func___str_array_push,0|He.__str116286);var f=(i+12|0)>>2,s=Me[f],n=0==(0|s);do{if(n){Se[f]=32;var o=Wr(r,128);if(0==(0|o)){var l=0;_=17;break}Se[i+16>>2]=o,_=11;break}if(Me[i+8>>2]>>>0>>0){_=11;break}var b=s<<3,k=Wr(r,b);if(0==(0|k)){var l=0;_=17;break}var u=k,c=i+16|0,h=Se[c>>2],d=Se[f]<<2;Pa(k,h,d,1);var w=Se[f]<<1;Se[f]=w,Se[c>>2]=u,_=11;break}while(0);do if(11==_){if((0|e)==-1)var p=Ca(a),E=p;else var E=e;var E,A=ja(a),g=E+1|0,y=Wr(r,g),t=(i+4|0)>>2,v=(i+16|0)>>2,m=(Se[t]<<2)+Se[v]|0;Se[m>>2]=y;var S=Se[Se[v]+(Se[t]<<2)>>2];if(0==(0|S)){Xa(0|He.__str72242,233,0|He.___func___str_array_push,0|He.__str117287);var M=Se[Se[v]+(Se[t]<<2)>>2]}else var M=S;var M;Pa(M,A,E,1),va(A),Ae[Se[Se[v]+(Se[t]<<2)>>2]+g|0]=0;var C=Se[t]+1|0;Se[t]=C;var R=i+8|0;if(C>>>0>2]>>>0){var l=1;break}Se[R>>2]=C;var l=1}while(0);var l;return l}function Xr(r,a,e,i,v){var t,f,_=Oe;Oe+=28;var s,n=_,o=_+8;Cr(o);var f=(r+12|0)>>2,l=0==(0|e),t=(0|n)>>2,b=n+4|0;r:do if(l)for(;;){var k=Se[f],u=Ae[k];if(u<<24>>24==0){s=12;break r}if(u<<24>>24==64){var c=k;s=7;break r}var h=Pr(r,n,a,1);if(0==(0|h)){var d=0;s=25;break r}var w=Se[t],p=Se[b>>2],E=Dr(r,0|He.__str170,(ne=Oe,Oe+=8,Se[ne>>2]=w,Se[ne+4>>2]=p,ne)),A=Fr(r,E,-1,o);if(0==(0|A)){var d=0;s=25;break r}var g=Se[t],y=Da(g,0|He.__str110280);if(0==(0|y)){s=12;break r}}else for(;;){var m=Se[f],S=Ae[m];if(S<<24>>24==0){s=12;break r}if(S<<24>>24==64){var c=m;s=7;break r}var M=Pr(r,n,a,1);if(0==(0|M)){var d=0;s=25;break r}var C=Se[t],R=Da(C,0|He.__str84254);if(0==(0|R)){s=13;break r}var T=Se[b>>2],O=Dr(r,0|He.__str170,(ne=Oe,Oe+=8,Se[ne>>2]=C,Se[ne+4>>2]=T,ne)),N=Fr(r,O,-1,o);if(0==(0|N)){var d=0;s=25;break r}var I=Se[t],P=Da(I,0|He.__str110280);if(0==(0|P)){s=12;break r}}while(0);do if(7==s){var c;Se[f]=c+1|0,s=12;break}while(0);do if(12==s){if(l){s=14;break}s=13;break}while(0);do if(13==s){var D=Se[f],L=D+1|0;if(Se[f]=L,Ae[D]<<24>>24==90){s=14;break}var d=0;s=25;break}while(0);r:do if(14==s){var F=o+4|0,X=Me[F>>2];do{if(0!=(0|X)){if(1==(0|X)){var j=o+16|0,U=Se[Se[j>>2]>>2],x=Da(U,0|He.__str84254);if(0==(0|x)){s=17;break}var z=j;s=20;break}var V=o+16|0;if(X>>>0<=1){var z=V;s=20;break}for(var B=0,H=1;;){var H,B,K=Se[Se[V>>2]+(H<<2)>>2],Y=Dr(r,0|He.__str112282,(ne=Oe,Oe+=8,Se[ne>>2]=B,Se[ne+4>>2]=K,ne)),G=H+1|0;if(G>>>0>=Me[F>>2]>>>0)break;var B=Y,H=G}if(0==(0|Y)){var z=V;s=20;break}var W=Y,Z=Y;s=21;break}s=17}while(0);if(17==s){var Q=i<<24>>24,q=v<<24>>24,$=Dr(r,0|He.__str111281,(ne=Oe,Oe+=8,Se[ne>>2]=Q,Se[ne+4>>2]=q,ne)),d=$;break}if(20==s)var z,W=Se[Se[z>>2]>>2],Z=0;var Z,W,J=v<<24>>24,rr=v<<24>>24==62;do if(rr){var ar=Ca(W);if(Ae[W+(ar-1)|0]<<24>>24!=62)break;var er=i<<24>>24,ir=Se[Se[o+16>>2]>>2],vr=Dr(r,0|He.__str113283,(ne=Oe,Oe+=16,Se[ne>>2]=er,Se[ne+4>>2]=ir,Se[ne+8>>2]=Z,Se[ne+12>>2]=J,ne)),d=vr;break r}while(0);var tr=i<<24>>24,fr=Se[Se[o+16>>2]>>2],_r=Dr(r,0|He.__str114284,(ne=Oe,Oe+=16,Se[ne>>2]=tr,Se[ne+4>>2]=fr,Se[ne+8>>2]=Z,Se[ne+12>>2]=J,ne)),d=_r}while(0);var d;return Oe=_,d}function jr(r){var a,e=Oe;Oe+=20;var i=e,v=r+24|0,t=Se[v>>2],a=(r+20|0)>>2,f=Se[a],_=r+44|0,s=Se[_>>2];Se[a]=t;var n=Kr(r);if(0==(0|n))var o=0;else{Cr(i);var l=Xr(r,i,0,60,62);if(0==(0|l))var b=n;else var k=Dr(r,0|He.__str170,(ne=Oe,Oe+=8,Se[ne>>2]=n,Se[ne+4>>2]=l,ne)),b=k;var b;Se[v>>2]=t,Se[a]=f,Se[_>>2]=s;var o=b}var o;return Oe=e,o}function Ur(r,a,e,i){var v,t=a>>2;Se[e>>2]=0,Se[t]=0;var f=0==(18&i|0);do{if(f){var _=r<<24>>24,s=1==((_-65)%2|0);if(0==(1&i|0)){if(s?Se[e>>2]=0|He.__str95265:v=14,65==(0|_)||66==(0|_)){Se[t]=0|He.__str96266,v=21;break}if(67==(0|_)||68==(0|_)){Se[t]=0|He.__str97267,v=21;break}if(69==(0|_)||70==(0|_)){Se[t]=0|He.__str98268,v=21;break}if(71==(0|_)||72==(0|_)){Se[t]=0|He.__str99269,v=21;break}if(73==(0|_)||74==(0|_)){Se[t]=0|He.__str100270,v=21;break}if(75==(0|_)||76==(0|_)){v=21;break}if(77==(0|_)){Se[t]=0|He.__str101271,v=21;break}var n=0;v=22;break}if(s?Se[e>>2]=0|He.__str88258:v=5,65==(0|_)||66==(0|_)){Se[t]=0|He.__str89259,v=21;break}if(67==(0|_)||68==(0|_)){Se[t]=0|He.__str90260,v=21;break}if(69==(0|_)||70==(0|_)){Se[t]=0|He.__str91261,v=21;break}if(71==(0|_)||72==(0|_)){Se[t]=0|He.__str92262,v=21;break}if(73==(0|_)||74==(0|_)){Se[t]=0|He.__str93263,v=21;break}if(75==(0|_)||76==(0|_)){v=21;break}if(77==(0|_)){Se[t]=0|He.__str94264,v=21;break}var n=0;v=22;break}v=21}while(0);if(21==v)var n=1;var n;return n}function xr(r,a,e){var i;Se[e>>2]=0;var i=(r+12|0)>>2,v=Se[i];if(Ae[v]<<24>>24==69){Se[e>>2]=0|He.__str102272;var t=Se[i]+1|0;Se[i]=t;var f=t}else var f=v;var f;Se[i]=f+1|0;var _=Ae[f]<<24>>24;if(65==(0|_)){Se[a>>2]=0;var s=1}else if(66==(0|_)){Se[a>>2]=0|He.__str103273;var s=1}else if(67==(0|_)){Se[a>>2]=0|He.__str104274;var s=1}else if(68==(0|_)){Se[a>>2]=0|He.__str105275;var s=1}else var s=0;var s;return s}function zr(r){var a,e,a=(r+12|0)>>2,i=r+40|0,v=r+20|0,t=0|i,f=r+44|0,_=r+48|0,s=r+52|0,n=r+56|0,o=r+20|0,l=r+24|0,b=r+16|0,k=0;r:for(;;){var k,u=Se[a],c=Ae[u];if(c<<24>>24==64){var h=u+1|0;Se[a]=h;var d=1;break}var w=c<<24>>24;do{if(0==(0|w)){var d=0;break r}if(48==(0|w)||49==(0|w)||50==(0|w)||51==(0|w)||52==(0|w)||53==(0|w)||54==(0|w)||55==(0|w)||56==(0|w)||57==(0|w)){var p=u+1|0;Se[a]=p;var E=(Ae[u]<<24>>24)-48|0,A=Yr(v,E),g=A;e=14;break}if(63==(0|w)){var y=u+1|0;Se[a]=y;var m=Ae[y]<<24>>24;if(36==(0|m)){var S=u+2|0;Se[a]=S;var M=jr(r);if(0==(0|M)){var d=0;break r}var C=Fr(r,M,-1,v);if(0==(0|C)){var d=0;break r}var R=M;e=15;break}if(63==(0|m)){var T=Se[t>>2],O=Se[f>>2],N=Se[_>>2],I=Se[s>>2],P=Se[n>>2],D=Se[o>>2],L=Se[l>>2];Cr(i);var F=Ir(r);if(0==(0|F))var X=k;else var j=Se[b>>2],U=Dr(r,0|He.__str109279,(ne=Oe,Oe+=4,Se[ne>>2]=j,ne)),X=U;var X;Se[o>>2]=D,Se[l>>2]=L,Se[t>>2]=T,Se[f>>2]=O,Se[_>>2]=N,Se[s>>2]=I,Se[n>>2]=P;var g=X;e=14;break}var x=Lr(r);if(0==(0|x)){var d=0;break r}var z=Dr(r,0|He.__str109279,(ne=Oe,Oe+=4,Se[ne>>2]=x,ne)),g=z;e=14;break}var V=Kr(r),g=V;e=14;break}while(0);if(14==e){var g;if(0==(0|g)){var d=0;break}var R=g}var R,B=Fr(r,R,-1,i);if(0==(0|B)){var d=0;break}var k=R}var d;return d}function Vr(r){var a,e,i,v=Oe;Oe+=36;var t,f=v,i=f>>2,_=v+4,s=v+8,e=s>>2,n=v+16;Se[i]=0;var o=0|r,l=Se[o>>2],b=0==(128&l|0),k=r+12|0;do if(b){var u=Ae[Se[k>>2]]<<24>>24;if(48==(0|u))var c=0|He.__str76246,h=k,a=h>>2;else if(49==(0|u))var c=0|He.__str77247,h=k,a=h>>2;else{if(50!=(0|u)){var c=0,h=k,a=h>>2;break}var c=0|He.__str78248,h=k,a=h>>2}}else var c=0,h=k,a=h>>2;while(0);var h,c,d=0==(512&l|0);do if(d){if((Ae[Se[a]]-48&255&255)>=3){var w=0;break}var w=0|He.__str79249}else var w=0;while(0);var w,p=Gr(r,0),E=Se[a],A=E+1|0;Se[a]=A;var g=Ae[E]<<24>>24;do{if(48==(0|g)||49==(0|g)||50==(0|g)||51==(0|g)||52==(0|g)||53==(0|g)){var y=r+44|0,m=Se[y>>2];Cr(n);var S=Pr(r,s,n,0);if(0==(0|S)){var M=0;t=28;break}var C=xr(r,f,_);if(0==(0|C)){var M=0;t=28;break}var R=Se[i],T=0==(0|R),O=Se[_>>2];do if(T)Se[i]=O;else{if(0==(0|O))break;var N=Dr(r,0|He.__str83253,(ne=Oe,Oe+=8,Se[ne>>2]=R,Se[ne+4>>2]=O,ne));Se[i]=N}while(0);Se[y>>2]=m,t=22;break}if(54==(0|g)||55==(0|g)){var I=s+4|0;Se[I>>2]=0,Se[e]=0;var P=xr(r,f,_);if(0==(0|P)){var M=0;t=28;break}if(Ae[Se[a]]<<24>>24==64){t=22;break}var D=qr(r);if(0==(0|D)){var M=0;t=28;break}var L=Dr(r,0|He.__str107277,(ne=Oe,Oe+=4,Se[ne>>2]=D,ne));Se[I>>2]=L,t=22;break}if(56==(0|g)||57==(0|g)){Se[e+1]=0,Se[e]=0,Se[i]=0,t=22;break}var M=0;t=28}while(0);if(22==t){var F=0==(4096&Se[o>>2]|0);do{if(F){var X=Se[e],j=Se[i];if(0==(0|j)){var U=X;t=26;break}var x=0!=(0|X)?0|He.__str87257:0,z=0|He.__str87257,V=j,B=x,H=X;t=27;break}Se[i]=0,Se[e+1]=0,Se[e]=0;var U=0;t=26;break}while(0);if(26==t)var U,K=0!=(0|U)?0|He.__str87257:0,z=K,V=0,B=0,H=U;var H,B,V,z,Y=Se[e+1],G=Dr(r,0|He.__str108278,(ne=Oe,Oe+=32,Se[ne>>2]=c,Se[ne+4>>2]=w,Se[ne+8>>2]=H,Se[ne+12>>2]=B,Se[ne+16>>2]=V,Se[ne+20>>2]=z,Se[ne+24>>2]=p,Se[ne+28>>2]=Y,ne));Se[r+16>>2]=G;var M=1}var M;return Oe=v,M}function Br(r,a){var e,i,v,t,f=Oe;Oe+=44;var _,s=f,t=s>>2,n=f+8,o=f+12,v=o>>2,l=f+16,b=f+20,k=f+40;Se[v]=0;var i=(r+12|0)>>2,u=Se[i],c=u+1|0;Se[i]=c;var h=ge[u],d=h<<24>>24,w=(h-65&255&255)>25;r:do if(w)var p=0;else{var e=(0|r)>>2,E=Me[e],A=0==(128&E|0),g=d-65|0;do if(A){var y=g/8|0;if(0==(0|y))var m=0|He.__str76246,S=g;else if(1==(0|y))var m=0|He.__str77247,S=g;else{if(2!=(0|y)){var m=0,S=g;break}var m=0|He.__str78248,S=g}}else var m=0,S=g;while(0);var S,m,M=0==(512&E|0)&h<<24>>24<89,C=(0|S)%8;do if(M)if(2==(0|C)||3==(0|C))var R=m,T=0|He.__str79249;else if(4==(0|C)||5==(0|C))var R=m,T=0|He.__str80250;else{if(6!=(0|C)&&7!=(0|C)){var R=m,T=0;break}var O=Dr(r,0|He.__str81251,(ne=Oe,Oe+=4,Se[ne>>2]=m,ne)),R=O,T=0|He.__str80250}else var R=m,T=0;while(0);var T,R,N=Gr(r,0),I=6==(0|C);do{if(!I){if(7==((d-56)%8|0)){_=14;break}var P=N;_=15;break}_=14}while(0);if(14==_)var D=Lr(r),L=Dr(r,0|He.__str82252,(ne=Oe,Oe+=8,Se[ne>>2]=N,Se[ne+4>>2]=D,ne)),P=L;var P,F=h<<24>>24>88;do if(F)var X=0;else{if((C-2|0)>>>0<2){var X=0;break}var j=xr(r,o,k);if(0==(0|j)){var p=0;break r}var U=Me[v],x=Se[k>>2];if(0==(0|U)&0==(0|x)){var X=0;break}var z=Dr(r,0|He.__str83253,(ne=Oe,Oe+=8,Se[ne>>2]=U,Se[ne+4>>2]=x,ne));Se[v]=z;var X=z}while(0);var X,V=Se[i],B=V+1|0;Se[i]=B;var H=Ae[V],K=Se[e],Y=Ur(H,n,l,K);if(0==(0|Y)){var p=0;break}Cr(b);var G=Se[i];if(Ae[G]<<24>>24==64){Se[t]=0|He.__str84254,Se[t+1]=0;var W=G+1|0;Se[i]=W}else{var Z=Pr(r,s,b,0);if(0==(0|Z)){var p=0;break}}if(0!=(4&Se[e]|0)&&(Se[t+1]=0,Se[t]=0),0==(0|a))var Q=P;else{var q=0|s,$=Se[q>>2],J=s+4|0,rr=Se[J>>2],ar=Dr(r,0|He.__str85255,(ne=Oe,Oe+=12,Se[ne>>2]=P,Se[ne+4>>2]=$,Se[ne+8>>2]=rr,ne));Se[J>>2]=0,Se[q>>2]=0;var Q=ar}var Q,er=r+44|0,ir=Se[er>>2],vr=Xr(r,b,1,40,41);if(0==(0|vr)){var p=0;break}if(0==(4096&Se[e]|0))var tr=vr,fr=X;else{Se[v]=0;var tr=0,fr=0}var fr,tr;Se[er>>2]=ir;var _r=Se[t],sr=Se[t+1];if(0==(0|_r))var nr=0;else var or=0!=(0|sr)?0:0|He.__str87257,nr=or;var nr,lr=Se[n>>2],br=0!=(0|lr)?0|He.__str87257:0,kr=Se[l>>2],ur=Dr(r,0|He.__str86256,(ne=Oe,Oe+=44,Se[ne>>2]=R,Se[ne+4>>2]=T,Se[ne+8>>2]=_r,Se[ne+12>>2]=nr,Se[ne+16>>2]=lr,Se[ne+20>>2]=br,Se[ne+24>>2]=kr,Se[ne+28>>2]=Q,Se[ne+32>>2]=tr,Se[ne+36>>2]=fr,Se[ne+40>>2]=sr,ne));Se[r+16>>2]=ur;var p=1}while(0);var p;return Oe=f,p}function Hr(r){var a,a=(r+12|0)>>2,e=Se[a];if(Ae[e]<<24>>24==36)var i=e;else{Xa(0|He.__str72242,1252,0|He.___func___handle_template,0|He.__str74244);var i=Se[a]}var i;Se[a]=i+1|0;var v=Kr(r),t=0==(0|v);do if(t)var f=0;else{var _=Xr(r,0,0,60,62);if(0==(0|_)){var f=0;break}var s=Dr(r,0|He.__str170,(ne=Oe,Oe+=8,Se[ne>>2]=v,Se[ne+4>>2]=_,ne));Se[r+16>>2]=s;var f=1}while(0);var f;return f}function Kr(r){for(var a,a=(r+12|0)>>2,e=Me[a],i=e,v=Ae[e];;){var v,i;if(!((v-65&255&255)<26|(v-97&255&255)<26|(v-48&255&255)<10)&&v<<24>>24!=95&&v<<24>>24!=36){var t=0;break}var f=i+1|0;Se[a]=f;var _=ge[f];if(_<<24>>24==64){Se[a]=i+2|0;var s=f-e|0,n=r+20|0,o=Fr(r,e,s,n);if(0==(0|o)){var t=0;break}var l=Se[r+24>>2]-1-Se[n>>2]|0,b=Yr(n,l),t=b;break}var i=f,v=_}var t;return t}function Yr(r,a){0==(0|r)&&Xa(0|He.__str72242,263,0|He.___func___str_array_get_ref,0|He.__str75245);var e=Se[r>>2]+a|0;if(e>>>0>2]>>>0)var i=Se[Se[r+16>>2]+(e<<2)>>2];else var i=0;var i;return i}function Gr(r,a){var e,e=(r+44|0)>>2,i=Me[e];if(i>>>0>a>>>0){for(var v=r+56|0,t=a,f=0,_=Se[v>>2],s=i;;){var s,_,f,t,n=Me[_+(t<<2)>>2];if(0==(0|n)){Xa(0|He.__str72242,680,0|He.___func___get_class_string,0|He.__str106276);var o=Se[v>>2],l=o,b=Se[o+(t<<2)>>2],k=Se[e]}else var l=_,b=n,k=s;var k,b,l,u=Ca(b),c=u+(f+2)|0,h=t+1|0;if(h>>>0>=k>>>0)break;var t=h,f=c,_=l,s=k}var d=c-1|0}else var d=-1;var d,w=Wr(r,d);if(0==(0|w))var p=0;else{var E=Se[e]-1|0,A=(0|E)<(0|a);r:do if(A)var g=0;else for(var y=r+56|0,m=0,S=E;;){var S,m,M=Se[Se[y>>2]+(S<<2)>>2],C=Ca(M),R=w+m|0;Pa(R,M,C,1);var T=C+m|0;if((0|S)>(0|a)){var O=T+1|0;Ae[w+T|0]=58;var N=T+2|0;Ae[w+O|0]=58;var I=N}else var I=T;var I,P=S-1|0;if((0|P)<(0|a)){var g=I;break r}var m=I,S=P}while(0);var g;Ae[w+g|0]=0;var p=w}var p;return p}function Wr(r,a){var e,i=a>>>0>1020;do if(i){var v=Se[r+4>>2],t=a+4|0,f=pe[v](t);if(0==(0|f)){var _=0;break}var s=r+60|0,n=Se[s>>2],o=f;Se[o>>2]=n,Se[s>>2]=f,Se[r+64>>2]=0;var _=f+4|0}else{var e=(r+64|0)>>2,l=Me[e];if(l>>>0>>0){var b=Se[r+4>>2],k=pe[b](1024);if(0==(0|k)){var _=0;break}var u=r+60|0,c=Se[u>>2],h=k;Se[h>>2]=c,Se[u>>2]=k,Se[e]=1020;var d=1020,w=k}else var d=l,w=Se[r+60>>2];var w,d;Se[e]=d-a|0;var _=w+(1024-d)|0}while(0);var _;return _}function Zr(r){var a=r<<24>>24;if(68==(0|a))var e=0|He.__str157327;else if(69==(0|a))var e=0|He.__str158328;else if(70==(0|a))var e=0|He.__str159329;else if(71==(0|a))var e=0|He.__str160330;else if(72==(0|a))var e=0|He.__str161331;else if(73==(0|a))var e=0|He.__str162332;else if(74==(0|a))var e=0|He.__str163333;else if(75==(0|a))var e=0|He.__str164334;else if(76==(0|a))var e=0|He.__str165335;else if(77==(0|a))var e=0|He.__str166336;else if(78==(0|a))var e=0|He.__str167337;else if(87==(0|a))var e=0|He.__str168338;else var e=0;var e;return e}function Qr(r){var a=r<<24>>24;if(67==(0|a))var e=0|He.__str145315;else if(68==(0|a))var e=0|He.__str146316;else if(69==(0|a))var e=0|He.__str147317;else if(70==(0|a))var e=0|He.__str148318;else if(71==(0|a))var e=0|He.__str149319;else if(72==(0|a))var e=0|He.__str150320;else if(73==(0|a))var e=0|He.__str151321;else if(74==(0|a))var e=0|He.__str152322;else if(75==(0|a))var e=0|He.__str153323;else if(77==(0|a))var e=0|He.__str154324;else if(78==(0|a))var e=0|He.__str155325;else if(79==(0|a))var e=0|He.__str156326;else if(88==(0|a))var e=0|He.__str84254;else if(90==(0|a))var e=0|He.__str110280;else var e=0;var e;return e}function qr(r){var a=r+44|0,e=Se[a>>2],i=zr(r);if(0==(0|i))var v=0;else var t=Gr(r,e),v=t;var v;return Se[a>>2]=e,v}function $r(r,a,e,i,v){var t,f,_,s=Oe;Oe+=16;var n,o=s,_=o>>2,l=s+4,b=s+8,f=b>>2;Se[l>>2]=0|ii;var t=(a+12|0)>>2,k=Se[t];if(Ae[k]<<24>>24==69){Se[l>>2]=0|He.__str134304;var u=k+1|0;Se[t]=u;var c=0|He.__str134304}else var c=0|ii;var c,h=i<<24>>24;do{if(65==(0|h)){var d=Dr(a,0|He.__str135305,(ne=Oe,Oe+=4,Se[ne>>2]=c,ne)),w=d;n=10;break}if(66==(0|h)){var p=Dr(a,0|He.__str136306,(ne=Oe,Oe+=4,Se[ne>>2]=c,ne)),w=p;n=10;break}if(80==(0|h)){var E=Dr(a,0|He.__str137307,(ne=Oe,Oe+=4,Se[ne>>2]=c,ne)),w=E;n=10;break}if(81==(0|h)){var A=Dr(a,0|He.__str138308,(ne=Oe,Oe+=4,Se[ne>>2]=c,ne)),w=A;n=10;break}if(82==(0|h)){var g=Dr(a,0|He.__str139309,(ne=Oe,Oe+=4,Se[ne>>2]=c,ne)),w=g;n=10;break}if(83==(0|h)){var y=Dr(a,0|He.__str140310,(ne=Oe,Oe+=4,Se[ne>>2]=c,ne)),w=y;n=10;break}if(63==(0|h)){var w=0|ii;n=10}else n=31}while(0);r:do if(10==n){var w,m=xr(a,o,l);if(0==(0|m))break;var S=a+44|0,M=Se[S>>2],C=Se[t],R=Ae[C]<<24>>24==89;a:do if(R){var T=C+1|0;Se[t]=T;var O=Lr(a);if(0==(0|O))break r;var N=Ha(O),I=Ae[w]<<24>>24==32,P=Se[_],D=0==(0|P);do{if(I){if(!D){n=17;break}var L=w+1|0;n=18;break}if(D){var L=w;n=18;break}n=17;break}while(0);if(17==n){var F=Dr(a,0|He.__str141311,(ne=Oe,Oe+=8,Se[ne>>2]=P,Se[ne+4>>2]=w,ne));Se[_]=0;var X=F}else if(18==n)var L,j=Dr(a,0|He.__str142312,(ne=Oe,Oe+=4,Se[ne>>2]=L,ne)),X=j;var X;if(0==(0|N)){var U=X;break}for(var x=X,z=N;;){var z,x,V=z-1|0,B=Lr(a),H=Dr(a,0|He.__str143313,(ne=Oe,Oe+=8,Se[ne>>2]=x,Se[ne+4>>2]=B,ne));if(0==(0|V)){var U=H;break a}var x=H,z=V}}else var U=w;while(0);var U,K=Pr(a,b,e,0);if(0==(0|K))break;var Y=Se[_];if(0==(0|Y)){var G=0==(0|v);do if(G){if(Ae[U]<<24>>24==0){var W=U;break}var Z=U+1|0;if(Ae[Z]<<24>>24!=42){var W=U;break}var Q=Se[f],q=Ca(Q);if(Ae[Q+(q-1)|0]<<24>>24!=42){var W=U;break}var W=Z}else var W=U;while(0);var W,$=Se[f],J=Dr(a,0|He.__str170,(ne=Oe,Oe+=8,Se[ne>>2]=$,Se[ne+4>>2]=W,ne));Se[r>>2]=J}else{var rr=Se[f],ar=Dr(a,0|He.__str144314,(ne=Oe,Oe+=12,Se[ne>>2]=rr,Se[ne+4>>2]=Y,Se[ne+8>>2]=U,ne));Se[r>>2]=ar}var er=Se[f+1];Se[r+4>>2]=er,Se[S>>2]=M}while(0);Oe=s}function Jr(r){var a,e=r>>>0<245;do{if(e){if(r>>>0<11)var i=16;else var i=r+11&-8;var i,v=i>>>3,t=Me[vi>>2],f=t>>>(v>>>0);if(0!=(3&f|0)){var _=(1&f^1)+v|0,s=_<<1,n=(s<<2)+vi+40|0,o=(s+2<<2)+vi+40|0,l=Me[o>>2],b=l+8|0,k=Me[b>>2];if((0|n)==(0|k))Se[vi>>2]=t&(1<<_^-1);else{if(k>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";Se[o>>2]=k,Se[k+12>>2]=n}var u=_<<3;Se[l+4>>2]=3|u;var c=l+(4|u)|0,h=1|Se[c>>2];Se[c>>2]=h;var d=b;a=38;break}if(i>>>0<=Me[vi+8>>2]>>>0){var w=i;a=30;break}if(0!=(0|f)){var p=2<>>12&16,y=A>>>(g>>>0),m=y>>>5&8,S=y>>>(m>>>0),M=S>>>2&4,C=S>>>(M>>>0),R=C>>>1&2,T=C>>>(R>>>0),O=T>>>1&1,N=(m|g|M|R|O)+(T>>>(O>>>0))|0,I=N<<1,P=(I<<2)+vi+40|0,D=(I+2<<2)+vi+40|0,L=Me[D>>2],F=L+8|0,X=Me[F>>2];if((0|P)==(0|X))Se[vi>>2]=t&(1<>>0>2]>>>0)throw Ka(),"Reached an unreachable!";Se[D>>2]=X,Se[X+12>>2]=P}var j=N<<3,U=j-i|0;Se[L+4>>2]=3|i;var x=L,z=x+i|0;Se[x+(4|i)>>2]=1|U,Se[x+j>>2]=U;var V=Me[vi+8>>2];if(0!=(0|V)){var B=Se[vi+20>>2],H=V>>>2&1073741822,K=(H<<2)+vi+40|0,Y=Me[vi>>2],G=1<<(V>>>3),W=0==(Y&G|0);do{if(!W){var Z=(H+2<<2)+vi+40|0,Q=Me[Z>>2];if(Q>>>0>=Me[vi+16>>2]>>>0){var q=Q,$=Z;break}throw Ka(),"Reached an unreachable!"}Se[vi>>2]=Y|G;var q=K,$=(H+2<<2)+vi+40|0}while(0);var $,q;Se[$>>2]=B,Se[q+12>>2]=B;var J=B+8|0;Se[J>>2]=q;var rr=B+12|0;Se[rr>>2]=K}Se[vi+8>>2]=U,Se[vi+20>>2]=z;var d=F;a=38;break}if(0==(0|Se[vi+4>>2])){var w=i;a=30;break}var ar=ra(i);if(0==(0|ar)){var w=i;a=30;break}var d=ar;a=38;break}if(r>>>0>4294967231){var w=-1;a=30;break}var er=r+11&-8;if(0==(0|Se[vi+4>>2])){var w=er;a=30;break}var ir=ea(er);if(0==(0|ir)){var w=er;a=30;break}var d=ir;a=38;break}while(0);if(30==a){var w,vr=Me[vi+8>>2];if(w>>>0>vr>>>0){var tr=Me[vi+12>>2];if(w>>>0>>0){var fr=tr-w|0;Se[vi+12>>2]=fr;var _r=Me[vi+24>>2],sr=_r;Se[vi+24>>2]=sr+w|0,Se[w+(sr+4)>>2]=1|fr,Se[_r+4>>2]=3|w;var d=_r+8|0}else var nr=aa(w),d=nr}else{var or=vr-w|0,lr=Me[vi+20>>2];if(or>>>0>15){var br=lr;Se[vi+20>>2]=br+w|0,Se[vi+8>>2]=or,Se[w+(br+4)>>2]=1|or,Se[br+vr>>2]=or,Se[lr+4>>2]=3|w}else{Se[vi+8>>2]=0,Se[vi+20>>2]=0,Se[lr+4>>2]=3|vr;var kr=vr+(lr+4)|0,ur=1|Se[kr>>2];Se[kr>>2]=ur}var d=lr+8|0}}var d;return d}function ra(r){var a,e,i,v=Se[vi+4>>2],t=(v&-v)-1|0,f=t>>>12&16,_=t>>>(f>>>0),s=_>>>5&8,n=_>>>(s>>>0),o=n>>>2&4,l=n>>>(o>>>0),b=l>>>1&2,k=l>>>(b>>>0),u=k>>>1&1,c=Me[vi+((s|f|o|b|u)+(k>>>(u>>>0))<<2)+304>>2],h=c,e=h>>2,d=(Se[c+4>>2]&-8)-r|0;r:for(;;)for(var d,h,w=h;;){var w,p=Se[w+16>>2];if(0==(0|p)){var E=Se[w+20>>2];if(0==(0|E))break r;var A=E}else var A=p;var A,g=(Se[A+4>>2]&-8)-r|0;if(g>>>0>>0){var h=A,e=h>>2,d=g;continue r}var w=A}var y=h,m=Me[vi+16>>2],S=y>>>0>>0;do if(!S){var M=y+r|0,C=M;if(y>>>0>=M>>>0)break;var R=Me[e+6],T=Me[e+3],O=(0|T)==(0|h);do if(O){var N=h+20|0,I=Se[N>>2];if(0==(0|I)){var P=h+16|0,D=Se[P>>2];if(0==(0|D)){var L=0,a=L>>2;break}var F=P,X=D}else{var F=N,X=I;i=14}for(;;){var X,F,j=X+20|0,U=Se[j>>2];if(0==(0|U)){var x=X+16|0,z=Me[x>>2];if(0==(0|z))break;var F=x,X=z}else var F=j,X=U}if(F>>>0>>0)throw Ka(),"Reached an unreachable!";Se[F>>2]=0;var L=X,a=L>>2}else{var V=Me[e+2];if(V>>>0>>0)throw Ka(),"Reached an unreachable!";Se[V+12>>2]=T,Se[T+8>>2]=V;var L=T,a=L>>2}while(0);var L,B=0==(0|R);r:do if(!B){var H=h+28|0,K=(Se[H>>2]<<2)+vi+304|0,Y=(0|h)==(0|Se[K>>2]);do{if(Y){if(Se[K>>2]=L,0!=(0|L))break;var G=Se[vi+4>>2]&(1<>2]^-1);Se[vi+4>>2]=G;break r}if(R>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";var W=R+16|0;if((0|Se[W>>2])==(0|h)?Se[W>>2]=L:Se[R+20>>2]=L,0==(0|L))break r}while(0);if(L>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";Se[a+6]=R;var Z=Me[e+4];if(0!=(0|Z)){if(Z>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";Se[a+4]=Z,Se[Z+24>>2]=L}var Q=Me[e+5];if(0==(0|Q))break;if(Q>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";Se[a+5]=Q,Se[Q+24>>2]=L}while(0);if(d>>>0<16){var q=d+r|0;Se[e+1]=3|q;var $=q+(y+4)|0,J=1|Se[$>>2];Se[$>>2]=J}else{Se[e+1]=3|r,Se[r+(y+4)>>2]=1|d,Se[y+d+r>>2]=d;var rr=Me[vi+8>>2];if(0!=(0|rr)){var ar=Me[vi+20>>2],er=rr>>>2&1073741822,ir=(er<<2)+vi+40|0,vr=Me[vi>>2],tr=1<<(rr>>>3),fr=0==(vr&tr|0);do{if(!fr){var _r=(er+2<<2)+vi+40|0,sr=Me[_r>>2];if(sr>>>0>=Me[vi+16>>2]>>>0){var nr=sr,or=_r;break}throw Ka(),"Reached an unreachable!"}Se[vi>>2]=vr|tr;var nr=ir,or=(er+2<<2)+vi+40|0}while(0);var or,nr;Se[or>>2]=ar,Se[nr+12>>2]=ar,Se[ar+8>>2]=nr,Se[ar+12>>2]=ir}Se[vi+8>>2]=d,Se[vi+20>>2]=C}return h+8|0}while(0);throw Ka(),"Reached an unreachable!"}function aa(r){var a,e;0==(0|Se[ti>>2])&&ba();var i=0==(4&Se[vi+440>>2]|0);do{if(i){var v=Se[vi+24>>2],t=0==(0|v);do{if(!t){var f=v,_=ua(f);if(0==(0|_)){e=6;break}var s=Se[ti+8>>2],n=r+47-Se[vi+12>>2]+s&-s;if(n>>>0>=2147483647){e=14;break}var o=re(n);if((0|o)==(Se[_>>2]+Se[_+4>>2]|0)){var l=o,b=n,k=o;e=13;break}var u=o,c=n;e=15;break}e=6}while(0);do if(6==e){var h=re(0);if((0|h)==-1){e=14;break}var d=Se[ti+8>>2],w=d+(r+47)&-d,p=h,E=Se[ti+4>>2],A=E-1|0;if(0==(A&p|0))var g=w;else var g=w-p+(A+p&-E)|0;var g;if(g>>>0>=2147483647){e=14;break}var y=re(g);if((0|y)==(0|h)){var l=h,b=g,k=y;e=13;break}var u=y,c=g;e=15;break}while(0);if(13==e){var k,b,l;if((0|l)!=-1){var m=b,S=l;e=26;break}var u=k,c=b}else if(14==e){var M=4|Se[vi+440>>2];Se[vi+440>>2]=M,e=23;break}var c,u,C=0|-c,R=(0|u)!=-1&c>>>0<2147483647;do{if(R){if(c>>>0>=(r+48|0)>>>0){var T=c;e=21;break}var O=Se[ti+8>>2],N=r+47-c+O&-O;if(N>>>0>=2147483647){var T=c;e=21;break}var I=re(N);if((0|I)==-1){re(C);e=22;break}var T=N+c|0;e=21;break}var T=c;e=21}while(0);if(21==e){var T;if((0|u)!=-1){var m=T,S=u;e=26;break}}var P=4|Se[vi+440>>2];Se[vi+440>>2]=P,e=23;break}e=23}while(0);do if(23==e){var D=Se[ti+8>>2],L=D+(r+47)&-D;if(L>>>0>=2147483647){e=49;break}var F=re(L),X=re(0);if(!((0|X)!=-1&(0|F)!=-1&F>>>0>>0)){e=49;break}var j=X-F|0;if(j>>>0<=(r+40|0)>>>0|(0|F)==-1){e=49;break}var m=j,S=F;e=26;break}while(0);r:do if(26==e){var S,m,U=Se[vi+432>>2]+m|0;Se[vi+432>>2]=U,U>>>0>Me[vi+436>>2]>>>0&&(Se[vi+436>>2]=U);var x=Me[vi+24>>2],z=0==(0|x);a:do if(z){var V=Me[vi+16>>2];0==(0|V)|S>>>0>>0&&(Se[vi+16>>2]=S),Se[vi+444>>2]=S,Se[vi+448>>2]=m,Se[vi+456>>2]=0;var B=Se[ti>>2];Se[vi+36>>2]=B,Se[vi+32>>2]=-1,ha(),ca(S,m-40|0)}else{for(var H=vi+444|0,a=H>>2;;){var H;if(0==(0|H))break;var K=Me[a],Y=H+4|0,G=Me[Y>>2],W=K+G|0;if((0|S)==(0|W)){if(0!=(8&Se[a+3]|0))break;var Z=x;if(!(Z>>>0>=K>>>0&Z>>>0>>0))break;Se[Y>>2]=G+m|0;var Q=Se[vi+24>>2],q=Se[vi+12>>2]+m|0;ca(Q,q);break a}var H=Se[a+2],a=H>>2}S>>>0>2]>>>0&&(Se[vi+16>>2]=S);for(var $=S+m|0,J=vi+444|0;;){var J;if(0==(0|J))break;var rr=0|J,ar=Me[rr>>2];if((0|ar)==(0|$)){if(0!=(8&Se[J+12>>2]|0))break;Se[rr>>2]=S;var er=J+4|0,ir=Se[er>>2]+m|0;Se[er>>2]=ir;var vr=da(S,ar,r),tr=vr;e=50;break r}var J=Se[J+8>>2]}Ma(S,m)}while(0);var fr=Me[vi+12>>2];if(fr>>>0<=r>>>0){e=49;break}var _r=fr-r|0;Se[vi+12>>2]=_r;var sr=Me[vi+24>>2],nr=sr;Se[vi+24>>2]=nr+r|0,Se[r+(nr+4)>>2]=1|_r,Se[sr+4>>2]=3|r;var tr=sr+8|0;e=50;break}while(0);if(49==e){var or=Je();Se[or>>2]=12;var tr=0}var tr;return tr}function ea(r){var a,e,i,v,t,f,_=r>>2,s=0|-r,n=r>>>8,o=0==(0|n);do if(o)var l=0;else{if(r>>>0>16777215){var l=31;break}var b=(n+1048320|0)>>>16&8,k=n<>>16&4,c=k<>>16&2,d=14-(u|b|h)+(c<>>15)|0,l=r>>>((d+7|0)>>>0)&1|d<<1}while(0);var l,w=Me[vi+(l<<2)+304>>2],p=0==(0|w);r:do if(p)var E=0,A=s,g=0;else{if(31==(0|l))var y=0;else var y=25-(l>>>1)|0;for(var y,m=0,S=s,M=w,t=M>>2,C=r<>>0>>0){if((0|T)==(0|r)){var E=M,A=O,g=M;break r}var N=M,I=O}else var N=m,I=S;var I,N,P=Me[t+5],D=Me[((C>>>31<<2)+16>>2)+t],L=0==(0|P)|(0|P)==(0|D)?R:P;if(0==(0|D)){var E=N,A=I,g=L;break r}var m=N,S=I,M=D,t=M>>2,C=C<<1,R=L}}while(0);var g,A,E,F=0==(0|g)&0==(0|E);do if(F){var X=2<>2]&(X|-X);if(0==(0|j)){var U=g;break}var x=(j&-j)-1|0,z=x>>>12&16,V=x>>>(z>>>0),B=V>>>5&8,H=V>>>(B>>>0),K=H>>>2&4,Y=H>>>(K>>>0),G=Y>>>1&2,W=Y>>>(G>>>0),Z=W>>>1&1,U=Se[vi+((B|z|K|G|Z)+(W>>>(Z>>>0))<<2)+304>>2]}else var U=g;while(0);var U,Q=0==(0|U);r:do if(Q)var q=A,$=E,v=$>>2;else for(var J=U,i=J>>2,rr=A,ar=E;;){var ar,rr,J,er=(Se[i+1]&-8)-r|0,ir=er>>>0>>0,vr=ir?er:rr,tr=ir?J:ar,fr=Me[i+4];if(0==(0|fr)){var _r=Me[i+5];if(0==(0|_r)){var q=vr,$=tr,v=$>>2;break r}var J=_r,i=J>>2,rr=vr,ar=tr}else var J=fr,i=J>>2,rr=vr,ar=tr}while(0);var $,q,sr=0==(0|$);r:do{if(!sr){if(q>>>0>=(Se[vi+8>>2]-r|0)>>>0){var nr=0;break}var or=$,e=or>>2,lr=Me[vi+16>>2],br=or>>>0>>0;do if(!br){var kr=or+r|0,ur=kr;if(or>>>0>=kr>>>0)break;var cr=Me[v+6],hr=Me[v+3],dr=(0|hr)==(0|$);do if(dr){var wr=$+20|0,pr=Se[wr>>2];if(0==(0|pr)){var Er=$+16|0,Ar=Se[Er>>2];if(0==(0|Ar)){var gr=0,a=gr>>2;break}var yr=Er,mr=Ar}else{var yr=wr,mr=pr;f=28}for(;;){var mr,yr,Sr=mr+20|0,Mr=Se[Sr>>2];if(0==(0|Mr)){var Cr=mr+16|0,Rr=Me[Cr>>2];if(0==(0|Rr))break;var yr=Cr,mr=Rr}else var yr=Sr,mr=Mr}if(yr>>>0>>0)throw Ka(),"Reached an unreachable!";Se[yr>>2]=0;var gr=mr,a=gr>>2}else{var Tr=Me[v+2];if(Tr>>>0>>0)throw Ka(),"Reached an unreachable!";Se[Tr+12>>2]=hr,Se[hr+8>>2]=Tr;var gr=hr,a=gr>>2}while(0);var gr,Or=0==(0|cr);a:do if(!Or){var Nr=$+28|0,Ir=(Se[Nr>>2]<<2)+vi+304|0,Pr=(0|$)==(0|Se[Ir>>2]);do{if(Pr){if(Se[Ir>>2]=gr,0!=(0|gr))break;var Dr=Se[vi+4>>2]&(1<>2]^-1);Se[vi+4>>2]=Dr;break a}if(cr>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";var Lr=cr+16|0;if((0|Se[Lr>>2])==(0|$)?Se[Lr>>2]=gr:Se[cr+20>>2]=gr,0==(0|gr))break a}while(0);if(gr>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";Se[a+6]=cr;var Fr=Me[v+4];if(0!=(0|Fr)){if(Fr>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";Se[a+4]=Fr,Se[Fr+24>>2]=gr}var Xr=Me[v+5];if(0==(0|Xr))break;if(Xr>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";Se[a+5]=Xr,Se[Xr+24>>2]=gr}while(0);var jr=q>>>0<16;a:do if(jr){var Ur=q+r|0;Se[v+1]=3|Ur;var xr=Ur+(or+4)|0,zr=1|Se[xr>>2];Se[xr>>2]=zr}else if(Se[v+1]=3|r,Se[_+(e+1)]=1|q,Se[(q>>2)+e+_]=q,q>>>0<256){var Vr=q>>>2&1073741822,Br=(Vr<<2)+vi+40|0,Hr=Me[vi>>2],Kr=1<<(q>>>3),Yr=0==(Hr&Kr|0);do{if(!Yr){var Gr=(Vr+2<<2)+vi+40|0,Wr=Me[Gr>>2];if(Wr>>>0>=Me[vi+16>>2]>>>0){var Zr=Wr,Qr=Gr;break}throw Ka(),"Reached an unreachable!"}Se[vi>>2]=Hr|Kr;var Zr=Br,Qr=(Vr+2<<2)+vi+40|0}while(0);var Qr,Zr;Se[Qr>>2]=ur,Se[Zr+12>>2]=ur,Se[_+(e+2)]=Zr,Se[_+(e+3)]=Br}else{var qr=kr,$r=q>>>8,Jr=0==(0|$r);do if(Jr)var ra=0;else{if(q>>>0>16777215){var ra=31;break}var aa=($r+1048320|0)>>>16&8,ea=$r<>>16&4,va=ea<>>16&2,fa=14-(ia|aa|ta)+(va<>>15)|0,ra=q>>>((fa+7|0)>>>0)&1|fa<<1}while(0);var ra,_a=(ra<<2)+vi+304|0;Se[_+(e+7)]=ra;var sa=r+(or+16)|0;Se[_+(e+5)]=0,Se[sa>>2]=0;var na=Se[vi+4>>2],oa=1<>2]=la,Se[_a>>2]=qr,Se[_+(e+6)]=_a,Se[_+(e+3)]=qr,Se[_+(e+2)]=qr}else{if(31==(0|ra))var ba=0;else var ba=25-(ra>>>1)|0;for(var ba,ka=q<>2];;){var ua,ka;if((Se[ua+4>>2]&-8|0)==(0|q)){var ca=ua+8|0,ha=Me[ca>>2],da=Me[vi+16>>2],wa=ua>>>0>>0;do if(!wa){if(ha>>>0>>0)break;Se[ha+12>>2]=qr,Se[ca>>2]=qr,Se[_+(e+2)]=ha,Se[_+(e+3)]=ua,Se[_+(e+6)]=0;break a}while(0);throw Ka(),"Reached an unreachable!"}var pa=(ka>>>31<<2)+ua+16|0,Ea=Me[pa>>2];if(0==(0|Ea)){if(pa>>>0>=Me[vi+16>>2]>>>0){Se[pa>>2]=qr,Se[_+(e+6)]=ua,Se[_+(e+3)]=qr,Se[_+(e+2)]=qr;break a}throw Ka(),"Reached an unreachable!"}var ka=ka<<1,ua=Ea}}}while(0);var nr=$+8|0;break r}while(0);throw Ka(),"Reached an unreachable!"}var nr=0}while(0);var nr;return nr}function ia(r){var a;0==(0|Se[ti>>2])&&ba();var e=r>>>0<4294967232;r:do if(e){var i=Me[vi+24>>2];if(0==(0|i)){var v=0;break}var t=Me[vi+12>>2],f=t>>>0>(r+40|0)>>>0;do if(f){var _=Me[ti+8>>2],s=-40-r-1+t+_|0,n=Math.floor((s>>>0)/(_>>>0)),o=(n-1)*_|0,l=i,b=ua(l);if(0!=(8&Se[b+12>>2]|0))break;var k=re(0),a=(b+4|0)>>2;if((0|k)!=(Se[b>>2]+Se[a]|0))break;var u=o>>>0>2147483646?-2147483648-_|0:o,c=0|-u,h=re(c),d=re(0);if(!((0|h)!=-1&d>>>0>>0))break;var w=k-d|0;if((0|k)==(0|d))break;var p=Se[a]-w|0;Se[a]=p;var E=Se[vi+432>>2]-w|0;Se[vi+432>>2]=E;var A=Se[vi+24>>2],g=Se[vi+12>>2]-w|0;ca(A,g);var v=(0|k)!=(0|d);break r}while(0);if(Me[vi+12>>2]>>>0<=Me[vi+28>>2]>>>0){var v=0;break}Se[vi+28>>2]=-1;var v=0}else var v=0;while(0);var v;return 1&v}function va(r){var a,e,i,v,t,f,_,s=r>>2,n=0==(0|r);r:do if(!n){var o=r-8|0,l=o,b=Me[vi+16>>2],k=o>>>0>>0;a:do if(!k){var u=Me[r-4>>2],c=3&u;if(1==(0|c))break;var h=u&-8,f=h>>2,d=r+(h-8)|0,w=d,p=0==(1&u|0);e:do if(p){var E=Me[o>>2];if(0==(0|c))break r;var A=-8-E|0,t=A>>2,g=r+A|0,y=g,m=E+h|0;if(g>>>0>>0)break a;if((0|y)==(0|Se[vi+20>>2])){var v=(r+(h-4)|0)>>2;if(3!=(3&Se[v]|0)){var S=y,i=S>>2,M=m;break}Se[vi+8>>2]=m;var C=Se[v]&-2;Se[v]=C,Se[t+(s+1)]=1|m,Se[d>>2]=m;break r}if(E>>>0<256){var R=Me[t+(s+2)],T=Me[t+(s+3)];if((0|R)!=(0|T)){var O=((E>>>2&1073741822)<<2)+vi+40|0,N=(0|R)!=(0|O)&R>>>0>>0;do if(!N){if(!((0|T)==(0|O)|T>>>0>=b>>>0))break;Se[R+12>>2]=T,Se[T+8>>2]=R;var S=y,i=S>>2,M=m;break e}while(0);throw Ka(),"Reached an unreachable!"}var I=Se[vi>>2]&(1<<(E>>>3)^-1);Se[vi>>2]=I;var S=y,i=S>>2,M=m}else{var P=g,D=Me[t+(s+6)],L=Me[t+(s+3)],F=(0|L)==(0|P);do if(F){var X=A+(r+20)|0,j=Se[X>>2];if(0==(0|j)){var U=A+(r+16)|0,x=Se[U>>2];if(0==(0|x)){var z=0,e=z>>2;break}var V=U,B=x}else{var V=X,B=j;_=21}for(;;){var B,V,H=B+20|0,K=Se[H>>2];if(0==(0|K)){var Y=B+16|0,G=Me[Y>>2];if(0==(0|G))break;var V=Y,B=G}else var V=H,B=K}if(V>>>0>>0)throw Ka(),"Reached an unreachable!";Se[V>>2]=0;var z=B,e=z>>2}else{var W=Me[t+(s+2)];if(W>>>0>>0)throw Ka(),"Reached an unreachable!";Se[W+12>>2]=L,Se[L+8>>2]=W;var z=L,e=z>>2}while(0);var z;if(0==(0|D)){var S=y,i=S>>2,M=m;break}var Z=A+(r+28)|0,Q=(Se[Z>>2]<<2)+vi+304|0,q=(0|P)==(0|Se[Q>>2]);do{if(q){if(Se[Q>>2]=z,0!=(0|z))break;var $=Se[vi+4>>2]&(1<>2]^-1);Se[vi+4>>2]=$;var S=y,i=S>>2,M=m;break e}if(D>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";var J=D+16|0;if((0|Se[J>>2])==(0|P)?Se[J>>2]=z:Se[D+20>>2]=z,0==(0|z)){var S=y,i=S>>2,M=m;break e}}while(0);if(z>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";Se[e+6]=D;var rr=Me[t+(s+4)];if(0!=(0|rr)){if(rr>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";Se[e+4]=rr,Se[rr+24>>2]=z}var ar=Me[t+(s+5)];if(0==(0|ar)){var S=y,i=S>>2,M=m;break}if(ar>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";Se[e+5]=ar,Se[ar+24>>2]=z;var S=y,i=S>>2,M=m}}else var S=l,i=S>>2,M=h;while(0);var M,S,er=S;if(er>>>0>=d>>>0)break;var ir=r+(h-4)|0,vr=Me[ir>>2];if(0==(1&vr|0))break;var tr=0==(2&vr|0);do{if(tr){if((0|w)==(0|Se[vi+24>>2])){var fr=Se[vi+12>>2]+M|0;Se[vi+12>>2]=fr,Se[vi+24>>2]=S;var _r=1|fr;if(Se[i+1]=_r,(0|S)==(0|Se[vi+20>>2])&&(Se[vi+20>>2]=0,Se[vi+8>>2]=0),fr>>>0<=Me[vi+28>>2]>>>0)break r;ia(0);break r}if((0|w)==(0|Se[vi+20>>2])){var sr=Se[vi+8>>2]+M|0;Se[vi+8>>2]=sr,Se[vi+20>>2]=S;var nr=1|sr;Se[i+1]=nr;var or=er+sr|0;Se[or>>2]=sr;break r}var lr=(vr&-8)+M|0,br=vr>>>3,kr=vr>>>0<256;e:do if(kr){var ur=Me[s+f],cr=Me[((4|h)>>2)+s];if((0|ur)!=(0|cr)){var hr=((vr>>>2&1073741822)<<2)+vi+40|0,dr=(0|ur)==(0|hr);do{if(!dr){if(ur>>>0>2]>>>0){_=66;break}_=63;break}_=63}while(0);do if(63==_){if((0|cr)!=(0|hr)&&cr>>>0>2]>>>0)break;Se[ur+12>>2]=cr,Se[cr+8>>2]=ur;break e}while(0);throw Ka(),"Reached an unreachable!"}var wr=Se[vi>>2]&(1<>2]=wr}else{var pr=d,Er=Me[f+(s+4)],Ar=Me[((4|h)>>2)+s],gr=(0|Ar)==(0|pr);do if(gr){var yr=h+(r+12)|0,mr=Se[yr>>2];if(0==(0|mr)){var Sr=h+(r+8)|0,Mr=Se[Sr>>2];if(0==(0|Mr)){var Cr=0,a=Cr>>2;break}var Rr=Sr,Tr=Mr}else{var Rr=yr,Tr=mr;_=73}for(;;){var Tr,Rr,Or=Tr+20|0,Nr=Se[Or>>2];if(0==(0|Nr)){var Ir=Tr+16|0,Pr=Me[Ir>>2];if(0==(0|Pr))break;var Rr=Ir,Tr=Pr}else var Rr=Or,Tr=Nr}if(Rr>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";Se[Rr>>2]=0;var Cr=Tr,a=Cr>>2}else{var Dr=Me[s+f];if(Dr>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";Se[Dr+12>>2]=Ar, +Se[Ar+8>>2]=Dr;var Cr=Ar,a=Cr>>2}while(0);var Cr;if(0==(0|Er))break;var Lr=h+(r+20)|0,Fr=(Se[Lr>>2]<<2)+vi+304|0,Xr=(0|pr)==(0|Se[Fr>>2]);do{if(Xr){if(Se[Fr>>2]=Cr,0!=(0|Cr))break;var jr=Se[vi+4>>2]&(1<>2]^-1);Se[vi+4>>2]=jr;break e}if(Er>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";var Ur=Er+16|0;if((0|Se[Ur>>2])==(0|pr)?Se[Ur>>2]=Cr:Se[Er+20>>2]=Cr,0==(0|Cr))break e}while(0);if(Cr>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";Se[a+6]=Er;var xr=Me[f+(s+2)];if(0!=(0|xr)){if(xr>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";Se[a+4]=xr,Se[xr+24>>2]=Cr}var zr=Me[f+(s+3)];if(0==(0|zr))break;if(zr>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";Se[a+5]=zr,Se[zr+24>>2]=Cr}while(0);if(Se[i+1]=1|lr,Se[er+lr>>2]=lr,(0|S)!=(0|Se[vi+20>>2])){var Vr=lr;break}Se[vi+8>>2]=lr;break r}Se[ir>>2]=vr&-2,Se[i+1]=1|M,Se[er+M>>2]=M;var Vr=M}while(0);var Vr;if(Vr>>>0<256){var Br=Vr>>>2&1073741822,Hr=(Br<<2)+vi+40|0,Kr=Me[vi>>2],Yr=1<<(Vr>>>3),Gr=0==(Kr&Yr|0);do{if(!Gr){var Wr=(Br+2<<2)+vi+40|0,Zr=Me[Wr>>2];if(Zr>>>0>=Me[vi+16>>2]>>>0){var Qr=Zr,qr=Wr;break}throw Ka(),"Reached an unreachable!"}Se[vi>>2]=Kr|Yr;var Qr=Hr,qr=(Br+2<<2)+vi+40|0}while(0);var qr,Qr;Se[qr>>2]=S,Se[Qr+12>>2]=S,Se[i+2]=Qr,Se[i+3]=Hr;break r}var $r=S,Jr=Vr>>>8,ra=0==(0|Jr);do if(ra)var aa=0;else{if(Vr>>>0>16777215){var aa=31;break}var ea=(Jr+1048320|0)>>>16&8,va=Jr<>>16&4,_a=va<>>16&2,na=14-(fa|ea|sa)+(_a<>>15)|0,aa=Vr>>>((na+7|0)>>>0)&1|na<<1}while(0);var aa,oa=(aa<<2)+vi+304|0;Se[i+7]=aa,Se[i+5]=0,Se[i+4]=0;var la=Se[vi+4>>2],ba=1<>2]=ua,Se[oa>>2]=$r,Se[i+6]=oa,Se[i+3]=S,Se[i+2]=S}else{if(31==(0|aa))var ca=0;else var ca=25-(aa>>>1)|0;for(var ca,ha=Vr<>2];;){var da,ha;if((Se[da+4>>2]&-8|0)==(0|Vr)){var wa=da+8|0,pa=Me[wa>>2],Ea=Me[vi+16>>2],Aa=da>>>0>>0;do if(!Aa){if(pa>>>0>>0)break;Se[pa+12>>2]=$r,Se[wa>>2]=$r,Se[i+2]=pa,Se[i+3]=da,Se[i+6]=0;break e}while(0);throw Ka(),"Reached an unreachable!"}var ga=(ha>>>31<<2)+da+16|0,ya=Me[ga>>2];if(0==(0|ya)){if(ga>>>0>=Me[vi+16>>2]>>>0){Se[ga>>2]=$r,Se[i+6]=da,Se[i+3]=S,Se[i+2]=S;break e}throw Ka(),"Reached an unreachable!"}var ha=ha<<1,da=ya}}while(0);var ma=Se[vi+32>>2]-1|0;if(Se[vi+32>>2]=ma,0!=(0|ma))break r;ta();break r}while(0);throw Ka(),"Reached an unreachable!"}while(0)}function ta(){var r=Se[vi+452>>2],a=0==(0|r);r:do if(!a)for(var e=r;;){var e,i=Se[e+8>>2];if(0==(0|i))break r;var e=i}while(0);Se[vi+32>>2]=-1}function fa(r,a){if(0==(0|r))var e=Jr(a),i=e;else var v=la(r,a),i=v;var i;return i}function _a(r,a){var e,i=r>>>0<9;do if(i)var v=Jr(a),t=v;else{var f=r>>>0<16?16:r,_=0==(f-1&f|0);r:do if(_)var s=f;else{if(f>>>0<=16){var s=16;break}for(var n=16;;){var n,o=n<<1;if(o>>>0>=f>>>0){var s=o;break r}var n=o}}while(0);var s;if((-64-s|0)>>>0>a>>>0){if(a>>>0<11)var l=16;else var l=a+11&-8;var l,b=Jr(l+(s+12)|0);if(0==(0|b)){var t=0;break}var k=b-8|0;if(0==((b>>>0)%(s>>>0)|0))var u=k,c=0;else{var h=b+(s-1)&-s,d=h-8|0,w=k;if((d-w|0)>>>0>15)var p=d;else var p=h+(s-8)|0;var p,E=p-w|0,e=(b-4|0)>>2,A=Se[e],g=(A&-8)-E|0;if(0==(3&A|0)){var y=Se[k>>2]+E|0;Se[p>>2]=y,Se[p+4>>2]=g;var u=p,c=0}else{var m=p+4|0,S=g|1&Se[m>>2]|2;Se[m>>2]=S;var M=g+(p+4)|0,C=1|Se[M>>2];Se[M>>2]=C;var R=E|1&Se[e]|2;Se[e]=R;var T=b+(E-4)|0,O=1|Se[T>>2];Se[T>>2]=O;var u=p,c=b}}var c,u,N=u+4|0,I=Me[N>>2],P=0==(3&I|0);do if(P)var D=0;else{var L=I&-8;if(L>>>0<=(l+16|0)>>>0){var D=0;break}var F=L-l|0;Se[N>>2]=l|1&I|2,Se[u+(4|l)>>2]=3|F;var X=u+(4|L)|0,j=1|Se[X>>2];Se[X>>2]=j;var D=l+(u+8)|0}while(0);var D;0!=(0|c)&&va(c),0!=(0|D)&&va(D);var t=u+8|0}else{var U=Je();Se[U>>2]=12;var t=0}}while(0);var t;return t}function sa(r,a,e,i){var v,t;0==(0|Se[ti>>2])&&ba();var f=0==(0|i),_=0==(0|r);do{if(f){if(_){var s=Jr(0),n=s;t=30;break}var o=r<<2;if(o>>>0<11){var l=0,b=16;t=9;break}var l=0,b=o+11&-8;t=9;break}if(_){var n=i;t=30;break}var l=i,b=0;t=9;break}while(0);do if(9==t){var b,l,k=0==(1&e|0);r:do if(k){if(_){var u=0,c=0;break}for(var h=0,d=0;;){var d,h,w=Me[a+(d<<2)>>2];if(w>>>0<11)var p=16;else var p=w+11&-8;var p,E=p+h|0,A=d+1|0;if((0|A)==(0|r)){var u=0,c=E;break r}var h=E,d=A}}else{var g=Me[a>>2];if(g>>>0<11)var y=16;else var y=g+11&-8;var y,u=y,c=y*r|0}while(0);var c,u,m=Jr(b-4+c|0);if(0==(0|m)){var n=0;break}var S=m-8|0,M=Se[m-4>>2]&-8;if(0!=(2&e|0)){var C=-4-b+M|0;Fa(m,0,C,1)}if(0==(0|l)){var R=m+c|0,T=M-c|3;Se[m+(c-4)>>2]=T;var O=R,v=O>>2,N=c}else var O=l,v=O>>2,N=M;var N,O;Se[v]=m;var I=r-1|0,P=0==(0|I);r:do if(P)var D=S,L=N;else if(0==(0|u))for(var F=S,X=N,j=0;;){var j,X,F,U=Me[a+(j<<2)>>2];if(U>>>0<11)var x=16;else var x=U+11&-8;var x,z=X-x|0;Se[F+4>>2]=3|x;var V=F+x|0,B=j+1|0;if(Se[(B<<2>>2)+v]=x+(F+8)|0,(0|B)==(0|I)){var D=V,L=z;break r}var F=V,X=z,j=B}else for(var H=3|u,K=u+8|0,Y=S,G=N,W=0;;){var W,G,Y,Z=G-u|0;Se[Y+4>>2]=H;var Q=Y+u|0,q=W+1|0;if(Se[(q<<2>>2)+v]=Y+K|0,(0|q)==(0|I)){var D=Q,L=Z;break r}var Y=Q,G=Z,W=q}while(0);var L,D;Se[D+4>>2]=3|L;var n=O}while(0);var n;return n}function na(r){var a=r>>2;0==(0|Se[ti>>2])&&ba();var e=Me[vi+24>>2];if(0==(0|e))var i=0,v=0,t=0,f=0,_=0,s=0,n=0;else{for(var o=Me[vi+12>>2],l=o+40|0,b=vi+444|0,k=l,u=l,c=1;;){var c,u,k,b,h=Me[b>>2],d=h+8|0;if(0==(7&d|0))var w=0;else var w=7&-d;for(var w,p=b+4|0,E=h+w|0,A=c,g=u,y=k;;){var y,g,A,E;if(E>>>0>>0)break;if(E>>>0>=(h+Se[p>>2]|0)>>>0|(0|E)==(0|e))break;var m=Se[E+4>>2];if(7==(0|m))break;var S=m&-8,M=S+y|0;if(1==(3&m|0))var C=A+1|0,R=S+g|0;else var C=A,R=g;var R,C,E=E+S|0,A=C,g=R,y=M}var T=Me[b+8>>2];if(0==(0|T))break;var b=T,k=y,u=g,c=A}var O=Se[vi+432>>2],i=y,v=A,t=o,f=g,_=O-y|0,s=Se[vi+436>>2],n=O-g|0}var n,s,_,f,t,v,i;Se[a]=i,Se[a+1]=v,Se[a+2]=0,Se[a+3]=0,Se[a+4]=_,Se[a+5]=s,Se[a+6]=0,Se[a+7]=n,Se[a+8]=f,Se[a+9]=t}function oa(){0==(0|Se[ti>>2])&&ba();var r=Me[vi+24>>2],a=0==(0|r);r:do if(a)var e=0,i=0,v=0;else for(var t=Se[vi+436>>2],f=Me[vi+432>>2],_=vi+444|0,s=f-40-Se[vi+12>>2]|0;;){var s,_,n=Me[_>>2],o=n+8|0;if(0==(7&o|0))var l=0;else var l=7&-o;for(var l,b=_+4|0,k=n+l|0,u=s;;){var u,k;if(k>>>0>>0)break;if(k>>>0>=(n+Se[b>>2]|0)>>>0|(0|k)==(0|r))break;var c=Se[k+4>>2];if(7==(0|c))break;var h=c&-8,d=1==(3&c|0)?h:0,w=u-d|0,k=k+h|0,u=w}var p=Me[_+8>>2];if(0==(0|p)){var e=t,i=f,v=u;break r}var _=p,s=u}while(0);var v,i,e,E=Se[Se[qe>>2]+12>>2],A=(Qa(E,0|He.__str339,(ne=Oe,Oe+=4,Se[ne>>2]=e,ne)),Se[Se[qe>>2]+12>>2]),g=(Qa(A,0|He.__str1340,(ne=Oe,Oe+=4,Se[ne>>2]=i,ne)),Se[Se[qe>>2]+12>>2]);Qa(g,0|He.__str2341,(ne=Oe,Oe+=4,Se[ne>>2]=v,ne))}function la(r,a){var e,i,v,t=a>>>0>4294967231;r:do{if(!t){var f=r-8|0,_=f,i=(r-4|0)>>2,s=Me[i],n=s&-8,o=n-8|0,l=r+o|0,b=f>>>0>2]>>>0;do if(!b){var k=3&s;if(!(1!=(0|k)&(0|o)>-8))break;var e=(r+(n-4)|0)>>2;if(0==(1&Se[e]|0))break;if(a>>>0<11)var u=16;else var u=a+11&-8;var u,c=0==(0|k);do{if(c){var h=ka(_,u),d=0,w=h;v=17;break}if(n>>>0>>0){if((0|l)!=(0|Se[vi+24>>2])){v=21;break}var p=Se[vi+12>>2]+n|0;if(p>>>0<=u>>>0){v=21;break}var E=p-u|0,A=r+(u-8)|0;Se[i]=u|1&s|2;var g=1|E;Se[r+(u-4)>>2]=g,Se[vi+24>>2]=A,Se[vi+12>>2]=E;var d=0,w=_;v=17;break}var y=n-u|0;if(y>>>0<=15){var d=0,w=_;v=17;break}Se[i]=u|1&s|2,Se[r+(u-4)>>2]=3|y;var m=1|Se[e];Se[e]=m;var d=r+u|0,w=_;v=17;break}while(0);do if(17==v){var w,d;if(0==(0|w))break;0!=(0|d)&&va(d);var S=w+8|0;break r}while(0);var M=Jr(a);if(0==(0|M)){var S=0;break r}var C=0==(3&Se[i]|0)?8:4,R=n-C|0,T=R>>>0>>0?R:a;Pa(M,r,T,1),va(r);var S=M;break r}while(0);throw Ka(),"Reached an unreachable!"}var O=Je();Se[O>>2]=12;var S=0}while(0);var S;return S}function ba(){if(0==(0|Se[ti>>2])){var r=qa(8);if(0!=(r-1&r|0))throw Ka(),"Reached an unreachable!";Se[ti+8>>2]=r,Se[ti+4>>2]=r,Se[ti+12>>2]=-1,Se[ti+16>>2]=2097152,Se[ti+20>>2]=0,Se[vi+440>>2]=0;var a=$a(0);Se[ti>>2]=a&-16^1431655768}}function ka(r,a){var e=Se[r+4>>2]&-8,i=a>>>0<256;do if(i)var v=0;else{if(e>>>0>=(a+4|0)>>>0&&(e-a|0)>>>0<=Se[ti+8>>2]<<1>>>0){var v=r;break}var v=0}while(0);var v;return v}function ua(r){for(var a,e=vi+444|0,a=e>>2;;){var e,i=Me[a];if(i>>>0<=r>>>0&&(i+Se[a+1]|0)>>>0>r>>>0){var v=e;break}var t=Me[a+2];if(0==(0|t)){var v=0;break}var e=t,a=e>>2}var v;return v}function ca(r,a){var e=r,i=r+8|0;if(0==(7&i|0))var v=0;else var v=7&-i;var v,t=a-v|0;Se[vi+24>>2]=e+v|0,Se[vi+12>>2]=t,Se[v+(e+4)>>2]=1|t,Se[a+(e+4)>>2]=40;var f=Se[ti+16>>2];Se[vi+28>>2]=f}function ha(){for(var r=0;;){var r,a=r<<1,e=(a<<2)+vi+40|0;Se[vi+(a+3<<2)+40>>2]=e,Se[vi+(a+2<<2)+40>>2]=e;var i=r+1|0;if(32==(0|i))break;var r=i}}function da(r,a,e){var i,v,t,f,_=a>>2,s=r>>2,n=r+8|0;if(0==(7&n|0))var o=0;else var o=7&-n;var o,l=a+8|0;if(0==(7&l|0))var b=0,t=b>>2;else var b=7&-l,t=b>>2;var b,k=a+b|0,u=k,c=o+e|0,v=c>>2,h=r+c|0,d=h,w=k-(r+o)-e|0;Se[(o+4>>2)+s]=3|e;var p=(0|u)==(0|Se[vi+24>>2]);r:do if(p){var E=Se[vi+12>>2]+w|0;Se[vi+12>>2]=E,Se[vi+24>>2]=d;var A=1|E;Se[v+(s+1)]=A}else if((0|u)==(0|Se[vi+20>>2])){var g=Se[vi+8>>2]+w|0;Se[vi+8>>2]=g,Se[vi+20>>2]=d;var y=1|g;Se[v+(s+1)]=y;var m=r+g+c|0;Se[m>>2]=g}else{var S=Me[t+(_+1)];if(1==(3&S|0)){var M=S&-8,C=S>>>3,R=S>>>0<256;a:do if(R){var T=Me[((8|b)>>2)+_],O=Me[t+(_+3)];if((0|T)!=(0|O)){var N=((S>>>2&1073741822)<<2)+vi+40|0,I=(0|T)==(0|N);do{if(!I){if(T>>>0>2]>>>0){f=18;break}f=15;break}f=15}while(0);do if(15==f){if((0|O)!=(0|N)&&O>>>0>2]>>>0)break;Se[T+12>>2]=O,Se[O+8>>2]=T;break a}while(0);throw Ka(),"Reached an unreachable!"}var P=Se[vi>>2]&(1<>2]=P}else{var D=k,L=Me[((24|b)>>2)+_],F=Me[t+(_+3)],X=(0|F)==(0|D);do if(X){var j=16|b,U=j+(a+4)|0,x=Se[U>>2];if(0==(0|x)){var z=a+j|0,V=Se[z>>2];if(0==(0|V)){var B=0,i=B>>2;break}var H=z,K=V}else{var H=U,K=x;f=25}for(;;){var K,H,Y=K+20|0,G=Se[Y>>2];if(0==(0|G)){var W=K+16|0,Z=Me[W>>2];if(0==(0|Z))break;var H=W,K=Z}else var H=Y,K=G}if(H>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";Se[H>>2]=0;var B=K,i=B>>2}else{var Q=Me[((8|b)>>2)+_];if(Q>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";Se[Q+12>>2]=F,Se[F+8>>2]=Q;var B=F,i=B>>2}while(0);var B;if(0==(0|L))break;var q=b+(a+28)|0,$=(Se[q>>2]<<2)+vi+304|0,J=(0|D)==(0|Se[$>>2]);do{if(J){if(Se[$>>2]=B,0!=(0|B))break;var rr=Se[vi+4>>2]&(1<>2]^-1);Se[vi+4>>2]=rr;break a}if(L>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";var ar=L+16|0;if((0|Se[ar>>2])==(0|D)?Se[ar>>2]=B:Se[L+20>>2]=B,0==(0|B))break a}while(0);if(B>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";Se[i+6]=L;var er=16|b,ir=Me[(er>>2)+_];if(0!=(0|ir)){if(ir>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";Se[i+4]=ir,Se[ir+24>>2]=B}var vr=Me[(er+4>>2)+_];if(0==(0|vr))break;if(vr>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";Se[i+5]=vr,Se[vr+24>>2]=B}while(0);var tr=a+(M|b)|0,fr=M+w|0}else var tr=u,fr=w;var fr,tr,_r=tr+4|0,sr=Se[_r>>2]&-2;if(Se[_r>>2]=sr,Se[v+(s+1)]=1|fr,Se[(fr>>2)+s+v]=fr,fr>>>0<256){var nr=fr>>>2&1073741822,or=(nr<<2)+vi+40|0,lr=Me[vi>>2],br=1<<(fr>>>3),kr=0==(lr&br|0);do{if(!kr){var ur=(nr+2<<2)+vi+40|0,cr=Me[ur>>2];if(cr>>>0>=Me[vi+16>>2]>>>0){var hr=cr,dr=ur;break}throw Ka(),"Reached an unreachable!"}Se[vi>>2]=lr|br;var hr=or,dr=(nr+2<<2)+vi+40|0}while(0);var dr,hr;Se[dr>>2]=d,Se[hr+12>>2]=d,Se[v+(s+2)]=hr,Se[v+(s+3)]=or}else{var wr=h,pr=fr>>>8,Er=0==(0|pr);do if(Er)var Ar=0;else{if(fr>>>0>16777215){var Ar=31;break}var gr=(pr+1048320|0)>>>16&8,yr=pr<>>16&4,Sr=yr<>>16&2,Cr=14-(mr|gr|Mr)+(Sr<>>15)|0,Ar=fr>>>((Cr+7|0)>>>0)&1|Cr<<1}while(0);var Ar,Rr=(Ar<<2)+vi+304|0;Se[v+(s+7)]=Ar;var Tr=c+(r+16)|0;Se[v+(s+5)]=0,Se[Tr>>2]=0;var Or=Se[vi+4>>2],Nr=1<>2]=Ir,Se[Rr>>2]=wr,Se[v+(s+6)]=Rr,Se[v+(s+3)]=wr,Se[v+(s+2)]=wr}else{if(31==(0|Ar))var Pr=0;else var Pr=25-(Ar>>>1)|0;for(var Pr,Dr=fr<>2];;){var Lr,Dr;if((Se[Lr+4>>2]&-8|0)==(0|fr)){var Fr=Lr+8|0,Xr=Me[Fr>>2],jr=Me[vi+16>>2],Ur=Lr>>>0>>0;do if(!Ur){if(Xr>>>0>>0)break;Se[Xr+12>>2]=wr,Se[Fr>>2]=wr,Se[v+(s+2)]=Xr,Se[v+(s+3)]=Lr,Se[v+(s+6)]=0;break r}while(0);throw Ka(),"Reached an unreachable!"}var xr=(Dr>>>31<<2)+Lr+16|0,zr=Me[xr>>2];if(0==(0|zr)){if(xr>>>0>=Me[vi+16>>2]>>>0){Se[xr>>2]=wr,Se[v+(s+6)]=Lr,Se[v+(s+3)]=wr,Se[v+(s+2)]=wr;break r}throw Ka(),"Reached an unreachable!"}var Dr=Dr<<1,Lr=zr}}}}while(0);return r+(8|o)|0}function wa(r){return 0|He.__str3342}function pa(r){return 0|He.__str14343}function Ea(r){Se[r>>2]=si+8|0}function Aa(r){0!=(0|r)&&va(r)}function ga(r){ya(r);var a=r;Aa(a)}function ya(r){var a=0|r;Ye(a)}function ma(r){var a=0|r;Ea(a),Se[r>>2]=ni+8|0}function Sa(r){var a=0|r;ya(a);var e=r;Aa(e)}function Ma(r,a){var e,i,v=Me[vi+24>>2],i=v>>2,t=v,f=ua(t),_=Se[f>>2],s=Se[f+4>>2],n=_+s|0,o=_+(s-39)|0;if(0==(7&o|0))var l=0;else var l=7&-o;var l,b=_+(s-47)+l|0,k=b>>>0<(v+16|0)>>>0?t:b,u=k+8|0,e=u>>2,c=u,h=r,d=a-40|0;ca(h,d);var w=k+4|0;Se[w>>2]=27,Se[e]=Se[vi+444>>2],Se[e+1]=Se[vi+448>>2],Se[e+2]=Se[vi+452>>2],Se[e+3]=Se[vi+456>>2],Se[vi+444>>2]=r,Se[vi+448>>2]=a,Se[vi+456>>2]=0,Se[vi+452>>2]=c;var p=k+28|0;Se[p>>2]=7;var E=(k+32|0)>>>0>>0;r:do if(E)for(var A=p;;){var A,g=A+4|0;if(Se[g>>2]=7,(A+8|0)>>>0>=n>>>0)break r;var A=g}while(0);var y=(0|k)==(0|t);r:do if(!y){var m=k-v|0,S=t+m|0,M=m+(t+4)|0,C=Se[M>>2]&-2;Se[M>>2]=C;var R=1|m;Se[i+1]=R;var T=S;if(Se[T>>2]=m,m>>>0<256){var O=m>>>2&1073741822,N=(O<<2)+vi+40|0,I=Me[vi>>2],P=1<<(m>>>3),D=0==(I&P|0);do{if(!D){var L=(O+2<<2)+vi+40|0,F=Me[L>>2];if(F>>>0>=Me[vi+16>>2]>>>0){var X=F,j=L;break}throw Ka(),"Reached an unreachable!"}var U=I|P;Se[vi>>2]=U;var X=N,j=(O+2<<2)+vi+40|0}while(0);var j,X;Se[j>>2]=v,Se[X+12>>2]=v,Se[i+2]=X,Se[i+3]=N}else{var x=v,z=m>>>8,V=0==(0|z);do if(V)var B=0;else{if(m>>>0>16777215){var B=31;break}var H=(z+1048320|0)>>>16&8,K=z<>>16&4,G=K<>>16&2,Z=14-(Y|H|W)+(G<>>15)|0,B=m>>>((Z+7|0)>>>0)&1|Z<<1}while(0);var B,Q=(B<<2)+vi+304|0;Se[i+7]=B,Se[i+5]=0,Se[i+4]=0;var q=Se[vi+4>>2],$=1<>2]=J,Se[Q>>2]=x,Se[i+6]=Q,Se[i+3]=v,Se[i+2]=v}else{if(31==(0|B))var rr=0;else var rr=25-(B>>>1)|0;for(var rr,ar=m<>2];;){var er,ar;if((Se[er+4>>2]&-8|0)==(0|m)){var ir=er+8|0,vr=Me[ir>>2],tr=Me[vi+16>>2],fr=er>>>0>>0;do if(!fr){if(vr>>>0>>0)break;Se[vr+12>>2]=x,Se[ir>>2]=x,Se[i+2]=vr,Se[i+3]=er,Se[i+6]=0;break r}while(0);throw Ka(),"Reached an unreachable!"}var _r=(ar>>>31<<2)+er+16|0,sr=Me[_r>>2];if(0==(0|sr)){if(_r>>>0>=Me[vi+16>>2]>>>0){Se[_r>>2]=x,Se[i+6]=er,Se[i+3]=v,Se[i+2]=v;break r}throw Ka(),"Reached an unreachable!"}var ar=ar<<1,er=sr}}}}while(0)}function Ca(r){return d(r)}function Ra(r,a){var e=0;do Ae[r+e]=Ae[a+e],e++;while(0!=Ae[a+e-1]);return r}function Ta(){var r=Ta;return r.LLVM_SAVEDSTACKS||(r.LLVM_SAVEDSTACKS=[]),r.LLVM_SAVEDSTACKS.push(le.stackSave()),r.LLVM_SAVEDSTACKS.length-1}function Oa(r){var a=Ta,e=a.LLVM_SAVEDSTACKS[r];a.LLVM_SAVEDSTACKS.splice(r,1),le.stackRestore(e)}function Na(r,a,e){for(var i=0;it?1:-1;i++}return 0}function Ia(r,a){var e=Ca(r),i=0;do Ae[r+e+i]=Ae[a+i],i++;while(0!=Ae[a+i-1]);return r}function Pa(r,a,e,i){if(e>=20&&a%2==r%2)if(a%4==r%4){for(var v=a+e;a%4;)Ae[r++]=Ae[a++];for(var t=a>>2,f=r>>2,_=v>>2;t<_;)Se[f++]=Se[t++];for(a=t<<2,r=f<<2;a>1,n=r>>1,o=v>>1;st?1:-1}return 0}function Fa(r,a,e,i){if(e>=20){for(var v=r+e;r%4;)Ae[r++]=a;a<0&&(a+=256);for(var t=r>>2,f=v>>2,_=a|a<<8|a<<16|a<<24;t>2],xe[1]=Se[a+_+4>>2],e=ze[0]):"i64"==r?e=[Se[a+_>>2],Se[a+_+4>>2]]:(r="i32",e=Se[a+_>>2]),_+=le.getNativeFieldSize(r),e}for(var i,v,t,f=r,_=0,s=[];;){var n=f;if(i=Ae[f],0===i)break;if(v=Ae[f+1],i=="%".charCodeAt(0)){var o=!1,l=!1,b=!1,k=!1;r:for(;;){switch(v){case"+".charCodeAt(0):o=!0;break;case"-".charCodeAt(0):l=!0;break;case"#".charCodeAt(0):b=!0;break;case"0".charCodeAt(0):if(k)break r;k=!0;break;default:break r}f++,v=Ae[f+1]}var u=0;if(v=="*".charCodeAt(0))u=e("i32"),f++,v=Ae[f+1];else for(;v>="0".charCodeAt(0)&&v<="9".charCodeAt(0);)u=10*u+(v-"0".charCodeAt(0)),f++,v=Ae[f+1];var c=!1;if(v==".".charCodeAt(0)){var h=0;if(c=!0,f++,v=Ae[f+1],v=="*".charCodeAt(0))h=e("i32"),f++;else for(;;){var d=Ae[f+1];if(d<"0".charCodeAt(0)||d>"9".charCodeAt(0))break;h=10*h+(d-"0".charCodeAt(0)),f++}v=Ae[f+1]}else var h=6;var E;switch(String.fromCharCode(v)){case"h":var A=Ae[f+2];A=="h".charCodeAt(0)?(f++,E=1):E=2;break;case"l":var A=Ae[f+2];A=="l".charCodeAt(0)?(f++,E=8):E=4;break;case"L":case"q":case"j":E=8;break;case"z":case"t":case"I":E=4;break;default:E=null}if(E&&f++,v=Ae[f+1],["d","i","u","o","x","X","p"].indexOf(String.fromCharCode(v))!=-1){var m=v=="d".charCodeAt(0)||v=="i".charCodeAt(0);E=E||4;var t=e("i"+8*E);if(8==E&&(t=le.makeBigInt(t[0],t[1],v=="u".charCodeAt(0))),E<=4){var S=Math.pow(256,E)-1;t=(m?y:g)(t&S,8*E)}var M,C=Math.abs(t),R="";if(v=="d".charCodeAt(0)||v=="i".charCodeAt(0))M=y(t,8*E,1).toString(10);else if(v=="u".charCodeAt(0))M=g(t,8*E,1).toString(10),t=Math.abs(t);else if(v=="o".charCodeAt(0))M=(b?"0":"")+C.toString(8);else if(v=="x".charCodeAt(0)||v=="X".charCodeAt(0)){if(R=b?"0x":"",t<0){t=-t,M=(C-1).toString(16);for(var T=[],O=0;OP&&P>=-4?(v=(v=="g".charCodeAt(0)?"f":"F").charCodeAt(0),h-=P+1):(v=(v=="g".charCodeAt(0)?"e":"E").charCodeAt(0),h--),I=Math.min(h,20)}v=="e".charCodeAt(0)||v=="E".charCodeAt(0)?(M=t.toExponential(I),/[eE][-+]\\d$/.test(M)&&(M=M.slice(0,-1)+"0"+M.slice(-1))):v!="f".charCodeAt(0)&&v!="F".charCodeAt(0)||(M=t.toFixed(I));var D=M.split("e");if(N&&!b)for(;D[0].length>1&&D[0].indexOf(".")!=-1&&("0"==D[0].slice(-1)||"."==D[0].slice(-1));)D[0]=D[0].slice(0,-1);else for(b&&M.indexOf(".")==-1&&(D[0]+=".");h>I++;)D[0]+="0";M=D[0]+(D.length>1?"e"+D[1]:""),v=="E".charCodeAt(0)&&(M=M.toUpperCase()),o&&t>=0&&(M="+"+M)}else M=(t<0?"-":"")+"inf",k=!1;for(;M.lengthh&&(L=L.slice(0,h))):L=p("(null)",!0),!l)for(;L.length0;)s.push(" ".charCodeAt(0));l||s.push(e("i8"))}else if(v=="n".charCodeAt(0)){var X=e("i32*");Se[X>>2]=s.length}else if(v=="%".charCodeAt(0))s.push(i);else for(var O=n;O="0".charCodeAt(0)&&r<="9".charCodeAt(0)}function Ha(r){for(var a;(a=Ae[r])&&Va(a);)r++;if(!a||!Ba(a))return 0;for(var e=r;(a=Ae[e])&&Ba(a);)e++;return Math.floor(Number(s(r).substr(0,e-r)))}function Ka(r){throw ke=!0,"ABORT: "+r+", at "+(new Error).stack}function Ya(r){return Ya.ret||(Ya.ret=_([0],"i32",we)),Se[Ya.ret>>2]=r,r}function Ga(r,a,e,i){var v=$e.streams[r];if(!v||v.object.isDevice)return Ya(Ge.EBADF),-1;if(v.isWrite){if(v.object.isFolder)return Ya(Ge.EISDIR),-1;if(e<0||i<0)return Ya(Ge.EINVAL),-1;for(var t=v.object.contents;t.length>2]=a),a}function Ja(){return Ya.ret}function re(r){var a=re;a.called||(Ie=o(Ie),a.called=!0);var e=Ie;return 0!=r&&le.staticAlloc(r),e}function ae(){return Se[ae.buf>>2]}function ee(r){r=r||Module.arguments,k();var a=null;return Module._main&&(a=Module.callMain(r),Module.noExitRuntime||u()),a}var ie=[],ve=false,te="object"==typeof window,fe="function"==typeof importScripts,_e=!te&&!ve&&!fe;if(ve){print=function(r){process.stdout.write(r+"\\n")},printErr=function(r){process.stderr.write(r+"\\n")};var se=require("fs");read=function(r){var a=se.readFileSync(r).toString();return a||"/"==r[0]||(r=__dirname.split("/").slice(0,-1).join("/")+"/src/"+r,a=se.readFileSync(r).toString()),a},load=function(a){r(read(a))},ie=process.argv.slice(2)}else if(_e)this.read||(this.read=function(r){snarf(r)}),"undefined"!=typeof scriptArgs?ie=scriptArgs:"undefined"!=typeof arguments&&(ie=arguments);else if(te)this.print=printErr=function(r){console.log(r)},this.read=function(r){var a=new XMLHttpRequest;return a.open("GET",r,!1),a.send(null),a.responseText},this.arguments&&(ie=arguments);else{if(!fe)throw"Unknown runtime environment. Where are we?";this.load=importScripts}"undefined"==typeof load&&"undefined"!=typeof read&&(this.load=function(a){r(read(a))}),"undefined"==typeof printErr&&(this.printErr=function(){}),"undefined"==typeof print&&(this.print=printErr);try{this.Module=Module}catch(r){this.Module=Module={}}Module.arguments||(Module.arguments=ie),Module.print&&(print=Module.print);var ne,oe,le={stackSave:function(){return Oe},stackRestore:function(r){Oe=r},forceAlign:function(r,a){if(a=a||4,1==a)return r;if(isNumber(r)&&isNumber(a))return Math.ceil(r/a)*a;if(isNumber(a)&&isPowerOfTwo(a)){var e=log2(a);return"(((("+r+")+"+(a-1)+")>>"+e+")<<"+e+")"}return"Math.ceil(("+r+")/"+a+")*"+a},isNumberType:function(r){return r in le.INT_TYPES||r in le.FLOAT_TYPES},isPointerType:function(r){return"*"==r[r.length-1]},isStructType:function(r){return!isPointerType(r)&&(!!/^\\[\\d+\\ x\\ (.*)\\]/.test(r)||(!!/?/.test(r)||"%"==r[0]))},INT_TYPES:{i1:0,i8:0,i16:0,i32:0,i64:0},FLOAT_TYPES:{float:0,double:0},bitshift64:function(r,e,i,v){var t=Math.pow(2,v)-1;if(v<32)switch(i){case"shl":return[r<>>32-v];case"ashr":return[(r>>>v|(e&t)<<32-v)>>0>>>0,e>>v>>>0];case"lshr":return[(r>>>v|(e&t)<<32-v)>>>0,e>>>v]}else if(32==v)switch(i){case"shl":return[0,r];case"ashr":return[e,(0|e)<0?t:0];case"lshr":return[e,0]}else switch(i){case"shl":return[0,r<>v-32>>>0,(0|e)<0?t:0];case"lshr":return[e>>>v-32,0]}a("unknown bitshift64 op: "+[value,i,v])},or64:function(r,a){var e=0|r|(0|a),i=4294967296*(Math.round(r/4294967296)|Math.round(a/4294967296));return e+i},and64:function(r,a){var e=(0|r)&(0|a),i=4294967296*(Math.round(r/4294967296)&Math.round(a/4294967296));return e+i},xor64:function(r,a){var e=(0|r)^(0|a),i=4294967296*(Math.round(r/4294967296)^Math.round(a/4294967296));return e+i},getNativeTypeSize:function(r,a){if(1==le.QUANTUM_SIZE)return 1;var i={"%i1":1,"%i8":1,"%i16":2,"%i32":4,"%i64":8,"%float":4,"%double":8}["%"+r];if(!i)if("*"==r[r.length-1])i=le.QUANTUM_SIZE;else if("i"==r[0]){var v=parseInt(r.substr(1));e(v%8==0),i=v/8}return i},getNativeFieldSize:function(r){return Math.max(le.getNativeTypeSize(r),le.QUANTUM_SIZE)},dedup:function(r,a){var e={};return a?r.filter(function(r){return!e[r[a]]&&(e[r[a]]=!0,!0)}):r.filter(function(r){return!e[r]&&(e[r]=!0,!0)})},set:function(){for(var r="object"==typeof arguments[0]?arguments[0]:arguments,a={},e=0;e=0&&a.push(f-e),e=f,f}),r.flatSize=le.alignMemory(r.flatSize,r.alignSize),0==a.length?r.flatFactor=r.flatSize:1==le.dedup(a).length&&(r.flatFactor=a[0]),r.needsFlattening=1!=r.flatFactor,r.flatIndexes},generateStructInfo:function(r,a,i){var v,t;if(a){if(i=i||0,v=("undefined"==typeof Types?le.typeInfo:Types.types)[a],!v)return null;e(v.fields.length===r.length,"Number of named fields must match the type for "+a),t=v.flatIndexes}else{var v={fields:r.map(function(r){return r[0]})};t=le.calculateStructAlignment(v)}var f={__size__:v.flatSize};return a?r.forEach(function(r,a){if("string"==typeof r)f[r]=t[a]+i;else{var e;for(var _ in r)e=_;f[e]=le.generateStructInfo(r[e],v.fields[a],t[a])}}):r.forEach(function(r,a){f[r[1]]=t[a]}),f},stackAlloc:function(r){var a=Oe;return Oe+=r,Oe=Oe+3>>2<<2,a},staticAlloc:function(r){var a=Ie;return Ie+=r,Ie=Ie+3>>2<<2,Ie>=Le&&l(),a},alignMemory:function(r,a){var e=r=Math.ceil(r/(a?a:4))*(a?a:4);return e},makeBigInt:function(r,a,e){var i=e?(r>>>0)+4294967296*(a>>>0):(r>>>0)+4294967296*(0|a);return i},QUANTUM_SIZE:4,__dummy__:0},be={MAX_ALLOWED:0,corrections:0,sigs:{},note:function(r,e,i){e||(this.corrections++,this.corrections>=this.MAX_ALLOWED&&a("\\n\\nToo many corrections!"))},print:function(){}},ke=!1,ue=0,ce=this;Module.ccall=i,Module.setValue=t,Module.getValue=f;var he=0,de=1,we=2;Module.ALLOC_NORMAL=he,Module.ALLOC_STACK=de,Module.ALLOC_STATIC=we,Module.allocate=_,Module.Pointer_stringify=s,Module.Array_stringify=n;var pe,Ee,Ae,ge,ye,me,Se,Me,Ce,Re,Te,Oe,Ne,Ie,Pe=4096,De=Module.TOTAL_STACK||5242880,Le=Module.TOTAL_MEMORY||10485760;Module.FAST_MEMORY||2097152;e(!!(Int32Array&&Float64Array&&new Int32Array(1).subarray&&new Int32Array(1).set),"Cannot fallback to non-typed array case: Code is too specialized");var Fe=new ArrayBuffer(Le);Ae=new Int8Array(Fe),ye=new Int16Array(Fe),Se=new Int32Array(Fe),ge=new Uint8Array(Fe),me=new Uint16Array(Fe),Me=new Uint32Array(Fe),Ce=new Float32Array(Fe),Re=new Float64Array(Fe),Se[0]=255,e(255===ge[0]&&0===ge[3],"Typed arrays 2 must be run on a little-endian system");var Xe=p("(null)");Ie=Xe.length;for(var je=0;je>2)),ze=(Ce.subarray(Ue>>2),Re.subarray(Ue>>3));Ne=Ue+8,Ie=o(Ne);var Ve=[],Be=[];Module.Array_copy=c,Module.TypedArray_copy=h,Module.String_len=d,Module.String_copy=w,Module.intArrayFromString=p,Module.intArrayToString=E,Module.writeStringToMemory=A;var He=[],Ke=0;O.X=1,N.X=1,V.X=1,H.X=1,G.X=1,W.X=1,q.X=1,$.X=1,rr.X=1,ar.X=1,er.X=1,vr.X=1,nr.X=1,or.X=1,kr.X=1,hr.X=1,Ar.X=1,Sr.X=1,Tr.X=1,Ir.X=1,Pr.X=1,Dr.X=1,Lr.X=1,Fr.X=1,Xr.X=1,zr.X=1,Vr.X=1,Br.X=1,Gr.X=1,$r.X=1,Module._malloc=Jr,Jr.X=1,ra.X=1,aa.X=1,ea.X=1,ia.X=1,Module._free=va,va.X=1,_a.X=1,sa.X=1,na.X=1,oa.X=1,la.X=1,da.X=1,Ma.X=1;var Ye,Ge={E2BIG:7,EACCES:13,EADDRINUSE:98,EADDRNOTAVAIL:99,EAFNOSUPPORT:97,EAGAIN:11,EALREADY:114,EBADF:9,EBADMSG:74,EBUSY:16,ECANCELED:125,ECHILD:10,ECONNABORTED:103,ECONNREFUSED:111,ECONNRESET:104,EDEADLK:35,EDESTADDRREQ:89,EDOM:33,EDQUOT:122,EEXIST:17,EFAULT:14,EFBIG:27,EHOSTUNREACH:113,EIDRM:43,EILSEQ:84,EINPROGRESS:115,EINTR:4,EINVAL:22,EIO:5,EISCONN:106,EISDIR:21,ELOOP:40,EMFILE:24,EMLINK:31,EMSGSIZE:90,EMULTIHOP:72,ENAMETOOLONG:36,ENETDOWN:100,ENETRESET:102,ENETUNREACH:101,ENFILE:23,ENOBUFS:105,ENODATA:61,ENODEV:19,ENOENT:2,ENOEXEC:8,ENOLCK:37,ENOLINK:67,ENOMEM:12,ENOMSG:42,ENOPROTOOPT:92,ENOSPC:28,ENOSR:63,ENOSTR:60,ENOSYS:38,ENOTCONN:107,ENOTDIR:20,ENOTEMPTY:39,ENOTRECOVERABLE:131,ENOTSOCK:88,ENOTSUP:95,ENOTTY:25,ENXIO:6,EOVERFLOW:75,EOWNERDEAD:130,EPERM:1,EPIPE:32,EPROTO:71,EPROTONOSUPPORT:93,EPROTOTYPE:91,ERANGE:34,EROFS:30,ESPIPE:29,ESRCH:3,ESTALE:116,ETIME:62,ETIMEDOUT:110,ETXTBSY:26,EWOULDBLOCK:11,EXDEV:18},We=0,Ze=0,Qe=0,qe=0,$e={currentPath:"/",nextInode:2,streams:[null],ignorePermissions:!0,absolutePath:function(r,a){if("string"!=typeof r)return null;void 0===a&&(a=$e.currentPath),r&&"/"==r[0]&&(a="");for(var e=a+"/"+r,i=e.split("/").reverse(),v=[""];i.length;){var t=i.pop();""==t||"."==t||(".."==t?v.length>1&&v.pop():v.push(t))}return 1==v.length?"/":v.join("/")},analyzePath:function(r,a,e){var i={isRoot:!1,exists:!1,error:0,name:null,path:null,object:null,parentExists:!1,parentPath:null,parentObject:null};if(r=$e.absolutePath(r),"/"==r)i.isRoot=!0,i.exists=i.parentExists=!0,i.name="/",i.path=i.parentPath="/",i.object=i.parentObject=$e.root;else if(null!==r){e=e||0,r=r.slice(1).split("/");for(var v=$e.root,t=[""];r.length;){1==r.length&&v.isFolder&&(i.parentExists=!0,i.parentPath=1==t.length?"/":t.join("/"),i.parentObject=v,i.name=r[0]);var f=r.shift();if(!v.isFolder){i.error=Ge.ENOTDIR;break}if(!v.read){i.error=Ge.EACCES;break}if(!v.contents.hasOwnProperty(f)){i.error=Ge.ENOENT;break}if(v=v.contents[f],v.link&&(!a||0!=r.length)){if(e>40){i.error=Ge.ELOOP;break}var _=$e.absolutePath(v.link,t.join("/"));return $e.analyzePath([_].concat(r).join("/"),a,e+1)}t.push(f),0==r.length&&(i.exists=!0,i.path=t.join("/"),i.object=v)}return i}return i},findObject:function(r,a){$e.ensureRoot();var e=$e.analyzePath(r,a);return e.exists?e.object:(Ya(e.error),null)},createObject:function(r,a,e,i,v){if(r||(r="/"),"string"==typeof r&&(r=$e.findObject(r)),!r)throw Ya(Ge.EACCES),new Error("Parent path must exist.");if(!r.isFolder)throw Ya(Ge.ENOTDIR), +new Error("Parent must be a folder.");if(!r.write&&!$e.ignorePermissions)throw Ya(Ge.EACCES),new Error("Parent folder must be writeable.");if(!a||"."==a||".."==a)throw Ya(Ge.ENOENT),new Error("Name must not be empty.");if(r.contents.hasOwnProperty(a))throw Ya(Ge.EEXIST),new Error("Can't overwrite object.");r.contents[a]={read:void 0===i||i,write:void 0!==v&&v,timestamp:Date.now(),inodeNumber:$e.nextInode++};for(var t in e)e.hasOwnProperty(t)&&(r.contents[a][t]=e[t]);return r.contents[a]},createFolder:function(r,a,e,i){var v={isFolder:!0,isDevice:!1,contents:{}};return $e.createObject(r,a,v,e,i)},createPath:function(r,a,e,i){var v=$e.findObject(r);if(null===v)throw new Error("Invalid parent.");for(a=a.split("/").reverse();a.length;){var t=a.pop();t&&(v.contents.hasOwnProperty(t)||$e.createFolder(v,t,e,i),v=v.contents[t])}return v},createFile:function(r,a,e,i,v){return e.isFolder=!1,$e.createObject(r,a,e,i,v)},createDataFile:function(r,a,e,i,v){if("string"==typeof e){for(var t=new Array(e.length),f=0,_=e.length;f<_;++f)t[f]=e.charCodeAt(f);e=t}var s={isDevice:!1,contents:e};return $e.createFile(r,a,s,i,v)},createLazyFile:function(r,a,e,i,v){var t={isDevice:!1,url:e};return $e.createFile(r,a,t,i,v)},createLink:function(r,a,e,i,v){var t={isDevice:!1,link:e};return $e.createFile(r,a,t,i,v)},createDevice:function(r,a,e,i){if(!e&&!i)throw new Error("A device must have at least one callback defined.");var v={isDevice:!0,input:e,output:i};return $e.createFile(r,a,v,Boolean(e),Boolean(i))},forceLoadFile:function(r){if(r.isDevice||r.isFolder||r.link||r.contents)return!0;var a=!0;if("undefined"!=typeof XMLHttpRequest)e("Cannot do synchronous binary XHRs in modern browsers. Use --embed-file or --preload-file in emcc");else{if("undefined"==typeof read)throw new Error("Cannot load without read() or XMLHttpRequest.");try{r.contents=p(read(r.url),!0)}catch(r){a=!1}}return a||Ya(Ge.EIO),a},ensureRoot:function(){$e.root||($e.root={read:!0,write:!0,isFolder:!0,isDevice:!1,timestamp:Date.now(),inodeNumber:1,contents:{}})},init:function(r,a,i){function v(r){null===r||r==="\\n".charCodeAt(0)?(a.printer(a.buffer.join("")),a.buffer=[]):a.buffer.push(String.fromCharCode(r))}e(!$e.init.initialized,"FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)"),$e.init.initialized=!0,$e.ensureRoot(),r=r||Module.stdin,a=a||Module.stdout,i=i||Module.stderr;var t=!0,f=!0,s=!0;r||(t=!1,r=function(){if(!r.cache||!r.cache.length){var a;"undefined"!=typeof window&&"function"==typeof window.prompt?a=window.prompt("Input: "):"function"==typeof readline&&(a=readline()),a||(a=""),r.cache=p(a+"\\n",!0)}return r.cache.shift()}),a||(f=!1,a=v),a.printer||(a.printer=print),a.buffer||(a.buffer=[]),i||(s=!1,i=v),i.printer||(i.printer=print),i.buffer||(i.buffer=[]),$e.createFolder("/","tmp",!0,!0);var n=$e.createFolder("/","dev",!0,!0),o=$e.createDevice(n,"stdin",r),l=$e.createDevice(n,"stdout",null,a),b=$e.createDevice(n,"stderr",null,i);$e.createDevice(n,"tty",r,a),$e.streams[1]={path:"/dev/stdin",object:o,position:0,isRead:!0,isWrite:!1,isAppend:!1,isTerminal:!t,error:!1,eof:!1,ungotten:[]},$e.streams[2]={path:"/dev/stdout",object:l,position:0,isRead:!1,isWrite:!0,isAppend:!1,isTerminal:!f,error:!1,eof:!1,ungotten:[]},$e.streams[3]={path:"/dev/stderr",object:b,position:0,isRead:!1,isWrite:!0,isAppend:!1,isTerminal:!s,error:!1,eof:!1,ungotten:[]},We=_([1],"void*",we),Ze=_([2],"void*",we),Qe=_([3],"void*",we),$e.createPath("/","dev/shm/tmp",!0,!0),$e.streams[We]=$e.streams[1],$e.streams[Ze]=$e.streams[2],$e.streams[Qe]=$e.streams[3],qe=_([_([0,0,0,0,We,0,0,0,Ze,0,0,0,Qe,0,0,0],"void*",we)],"void*",we)},quit:function(){$e.init.initialized&&($e.streams[2]&&$e.streams[2].object.output.buffer.length>0&&$e.streams[2].object.output("\\n".charCodeAt(0)),$e.streams[3]&&$e.streams[3].object.output.buffer.length>0&&$e.streams[3].object.output("\\n".charCodeAt(0)))}},Je=Ja;Ve.unshift({func:function(){$e.ignorePermissions=!1,$e.init.initialized||$e.init()}}),Be.push({func:function(){$e.quit()}}),Ya(0),ae.buf=_(12,"void*",we),Module.callMain=function(r){function a(){for(var r=0;r<3;r++)i.push(0)}var e=r.length+1,i=[_(p("/bin/this.program"),"i8",we)];a();for(var v=0;v>2]=0|He.__str,Se[ri+4>>2]=0|He.__str1,Se[ri+16>>2]=0|He.__str2,Se[ri+20>>2]=0|He.__str3,Se[ri+32>>2]=0|He.__str4,Se[ri+36>>2]=0|He.__str5,Se[ri+48>>2]=0|He.__str6,Se[ri+52>>2]=0|He.__str7,Se[ri+64>>2]=0|He.__str8,Se[ri+68>>2]=0|He.__str7,Se[ri+80>>2]=0|He.__str9,Se[ri+84>>2]=0|He.__str10,Se[ri+96>>2]=0|He.__str11,Se[ri+100>>2]=0|He.__str12,Se[ri+112>>2]=0|He.__str13,Se[ri+116>>2]=0|He.__str14,Se[ri+128>>2]=0|He.__str15,Se[ri+132>>2]=0|He.__str16,Se[ri+144>>2]=0|He.__str17,Se[ri+148>>2]=0|He.__str18,Se[ri+160>>2]=0|He.__str19,Se[ri+164>>2]=0|He.__str20,Se[ri+176>>2]=0|He.__str21,Se[ri+180>>2]=0|He.__str22,Se[ri+192>>2]=0|He.__str23,Se[ri+196>>2]=0|He.__str24,Se[ri+208>>2]=0|He.__str25,Se[ri+212>>2]=0|He.__str26,Se[ri+224>>2]=0|He.__str27,Se[ri+228>>2]=0|He.__str28,Se[ri+240>>2]=0|He.__str29,Se[ri+244>>2]=0|He.__str30,Se[ri+256>>2]=0|He.__str31,Se[ri+260>>2]=0|He.__str32,Se[ri+272>>2]=0|He.__str33,Se[ri+276>>2]=0|He.__str34,Se[ri+288>>2]=0|He.__str35,Se[ri+292>>2]=0|He.__str36,Se[ri+304>>2]=0|He.__str37,Se[ri+308>>2]=0|He.__str38,Se[ri+320>>2]=0|He.__str39,Se[ri+324>>2]=0|He.__str40,Se[ri+336>>2]=0|He.__str41,Se[ri+340>>2]=0|He.__str42,Se[ri+352>>2]=0|He.__str43,Se[ri+356>>2]=0|He.__str44,Se[ri+368>>2]=0|He.__str45,Se[ri+372>>2]=0|He.__str46,Se[ri+384>>2]=0|He.__str47,Se[ri+388>>2]=0|He.__str48,Se[ri+400>>2]=0|He.__str49,Se[ri+404>>2]=0|He.__str119289,Se[ri+416>>2]=0|He.__str51,Se[ri+420>>2]=0|He.__str20,Se[ri+432>>2]=0|He.__str52,Se[ri+436>>2]=0|He.__str53,Se[ri+448>>2]=0|He.__str54,Se[ri+452>>2]=0|He.__str55,Se[ri+464>>2]=0|He.__str56,Se[ri+468>>2]=0|He.__str57,Se[ri+480>>2]=0|He.__str58,Se[ri+484>>2]=0|He.__str119289,Se[ri+496>>2]=0|He.__str59,Se[ri+500>>2]=0|He.__str60,Se[ri+512>>2]=0|He.__str61,Se[ri+516>>2]=0|He.__str62,Se[ri+528>>2]=0|He.__str63,Se[ri+532>>2]=0|He.__str64,Se[ri+544>>2]=0|He.__str65,Se[ri+548>>2]=0|He.__str66,Se[ri+560>>2]=0|He.__str67,Se[ri+564>>2]=0|He.__str68,Se[ri+576>>2]=0|He.__str69,Se[ri+580>>2]=0|He.__str70,Se[ri+592>>2]=0|He.__str71,Se[ri+596>>2]=0|He.__str72,Se[ri+608>>2]=0|He.__str73,Se[ri+612>>2]=0|He.__str74,Se[ri+624>>2]=0|He.__str75,Se[ri+628>>2]=0|He.__str76,Se[ri+640>>2]=0|He.__str77,Se[ri+644>>2]=0|He.__str72,Se[ri+656>>2]=0|He.__str78,Se[ri+660>>2]=0|He.__str79,Se[ri+672>>2]=0|He.__str80,Se[ri+676>>2]=0|He.__str81,Se[ri+688>>2]=0|He.__str82,Se[ri+692>>2]=0|He.__str83,Se[ri+704>>2]=0|He.__str84,Se[ri+708>>2]=0|He.__str85,Se[ri+720>>2]=0|He.__str86,Se[ri+724>>2]=0|He.__str87,Se[ri+736>>2]=0|He.__str88,Se[ri+740>>2]=0|He.__str89,Se[ri+752>>2]=0|He.__str90,Se[ri+756>>2]=0|He.__str91,Se[ri+768>>2]=0|He.__str92,Se[ri+772>>2]=0|He.__str91,Se[ai>>2]=0|He.__str145315,Se[ai+8>>2]=0|He.__str145315,Se[ai+20>>2]=0|He.__str167337,Se[ai+28>>2]=0|He.__str95,Se[ai+40>>2]=0|He.__str146316,Se[ai+48>>2]=0|He.__str97,Se[ai+60>>2]=0|He.__str155325,Se[ai+68>>2]=0|He.__str155325,Se[ai+80>>2]=0|He.__str156326,Se[ai+88>>2]=0|He.__str156326,Se[ai+100>>2]=0|He.__str154324,Se[ai+108>>2]=0|He.__str154324,Se[ai+120>>2]=0|He.__str101,Se[ai+128>>2]=0|He.__str101,Se[ai+140>>2]=0|He.__str147317,Se[ai+148>>2]=0|He.__str147317,Se[ai+160>>2]=0|He.__str150320,Se[ai+168>>2]=0|He.__str150320,Se[ai+180>>2]=0|He.__str151321,Se[ai+188>>2]=0|He.__str105,Se[ai+220>>2]=0|He.__str152322,Se[ai+228>>2]=0|He.__str152322,Se[ai+240>>2]=0|He.__str153323,Se[ai+248>>2]=0|He.__str153323,Se[ai+260>>2]=0|He.__str165335,Se[ai+268>>2]=0|He.__str165335,Se[ai+280>>2]=0|He.__str166336,Se[ai+288>>2]=0|He.__str166336,Se[ai+360>>2]=0|He.__str148318,Se[ai+368>>2]=0|He.__str148318,Se[ai+380>>2]=0|He.__str149319,Se[ai+388>>2]=0|He.__str149319,Se[ai+420>>2]=0|He.__str84254,Se[ai+428>>2]=0|He.__str84254,Se[ai+440>>2]=0|He.__str168338,Se[ai+448>>2]=0|He.__str146316,Se[ai+460>>2]=0|He.__str114,Se[ai+468>>2]=0|He.__str152322,Se[ai+480>>2]=0|He.__str115,Se[ai+488>>2]=0|He.__str115,Se[ai+500>>2]=0|He.__str110280,Se[ai+508>>2]=0|He.__str110280,Se[ei+4>>2]=0|He.__str152,Se[ei+12>>2]=0|He.__str152,Se[ei+32>>2]=0|He.__str153,Se[ei+40>>2]=0|He.__str153,Se[ei+48>>2]=0|He.__str154,Se[ei+60>>2]=0|He.__str155,Se[ei+68>>2]=0|He.__str155,Se[ei+76>>2]=0|He.__str156,Se[ei+88>>2]=0|He.__str157,Se[ei+96>>2]=0|He.__str158,Se[ei+104>>2]=0|He.__str156,Se[ei+116>>2]=0|He.__str159,Se[ei+124>>2]=0|He.__str160,Se[ei+132>>2]=0|He.__str161,Se[ei+144>>2]=0|He.__str162,Se[ei+152>>2]=0|He.__str163,Se[ei+160>>2]=0|He.__str164,Se[ei+172>>2]=0|He.__str165,Se[ei+180>>2]=0|He.__str166,Se[ei+188>>2]=0|He.__str167,Se[si+4>>2]=bi,Se[ni+4>>2]=ki,oi=_([2,0,0,0,0],["i8*",0,0,0,0],we),Se[bi>>2]=oi+8|0,Se[bi+4>>2]=0|He.__ZTSSt9bad_alloc,Se[bi+8>>2]=li,Se[ki>>2]=oi+8|0,Se[ki+4>>2]=0|He.__ZTSSt20bad_array_new_length,Se[ki+8>>2]=bi,ui=16,ci=6,hi=18,di=6,wi=6,pe=[0,0,Jr,0,va,0,ya,0,ga,0,wa,0,Sa,0,pa,0,Ea,0,ma,0],Module.FUNCTION_TABLE=pe,Module.run=ee,Module.preRun&&Module.preRun(),0==Ke){ee()}Module.postRun&&Module.postRun(),Module.___cxa_demangle=G;var pi=v("__cxa_demangle","string",["string","string","number","number"]);return function(r){return pi(r,"",1,0)}}(); +` \ No newline at end of file diff --git a/src/speedscope/lib/file-format-spec.js b/src/speedscope/lib/file-format-spec.js new file mode 100644 index 0000000000000..9ac3e2fd6d701 --- /dev/null +++ b/src/speedscope/lib/file-format-spec.js @@ -0,0 +1,13 @@ +export var FileFormat; +(function (FileFormat) { + let ProfileType; + (function (ProfileType) { + ProfileType["EVENTED"] = "evented"; + ProfileType["SAMPLED"] = "sampled"; + })(ProfileType = FileFormat.ProfileType || (FileFormat.ProfileType = {})); + let EventType; + (function (EventType) { + EventType["OPEN_FRAME"] = "O"; + EventType["CLOSE_FRAME"] = "C"; + })(EventType = FileFormat.EventType || (FileFormat.EventType = {})); +})(FileFormat || (FileFormat = {})); diff --git a/src/speedscope/lib/flamechart.js b/src/speedscope/lib/flamechart.js new file mode 100644 index 0000000000000..d72684eeea2a3 --- /dev/null +++ b/src/speedscope/lib/flamechart.js @@ -0,0 +1,97 @@ +import { lastOf } from './utils'; +import { clamp } from './math'; + +export class Flamechart { + constructor(source) { + this.source = source; + // Bottom to top + this.layers = []; + this.totalWeight = 0; + this.minFrameWidth = 1; + const stack = []; + const openFrame = (node, value) => { + const parent = lastOf(stack); + const frame = { + node, + parent, + children: [], + start: value, + end: value, + }; + if (parent) { + parent.children.push(frame); + } + stack.push(frame); + }; + this.minFrameWidth = Infinity; + const closeFrame = (node, value) => { + console.assert(stack.length > 0); + const stackTop = stack.pop(); + stackTop.end = value; + if (stackTop.end - stackTop.start === 0) + return; + const layerIndex = stack.length; + while (this.layers.length <= layerIndex) + this.layers.push([]); + this.layers[layerIndex].push(stackTop); + this.minFrameWidth = Math.min(this.minFrameWidth, stackTop.end - stackTop.start); + }; + this.totalWeight = source.getTotalWeight(); + source.forEachCall(openFrame, closeFrame); + if (!isFinite(this.minFrameWidth)) + this.minFrameWidth = 1; + } + getTotalWeight() { + return this.totalWeight; + } + getLayers() { + return this.layers; + } + getColorBucketForFrame(frame) { + return this.source.getColorBucketForFrame(frame); + } + getMinFrameWidth() { + return this.minFrameWidth; + } + formatValue(v) { + return this.source.formatValue(v); + } + getClampedViewportWidth(viewportWidth) { + const maxWidth = this.getTotalWeight(); + // In order to avoid floating point error, we cap the maximum zoom. In + // particular, it's important that at the maximum zoom level, the total + // trace size + a viewport width is not equal to the trace size due to + // floating point rounding. + // + // For instance, if the profile's total weight is 2^60, and the viewport + // size is 1, trying to move one viewport width right will result in no + // change because 2^60 + 1 = 2^60 in floating point arithmetic. JavaScript + // numbers are 64 bit floats, and therefore have 53 mantissa bits. You can + // see this for yourself in the console. Try: + // + // > Math.pow(2, 60) + 1 === Math.pow(2, 60) + // true + // > Math.pow(2, 53) + 1 === Math.pow(2, 53) + // true + // > Math.pow(2, 52) + 1 === Math.pow(2, 52) + // false + // + // We use 2^40 as a cap instead, since we want to be able to make small + // adjustments within a viewport width. + // + // For reference, this will still allow you to zoom until 1 nanosecond fills + // the screen in a profile with a duration of over 18 minutes. + // + // > Math.pow(2, 40) / (60 * Math.pow(10, 9)) + // 18.325193796266667 + // + const maxZoom = Math.pow(2, 40); + // In addition to capping zoom to avoid floating point error, we further cap + // zoom to avoid letting you zoom in so that the smallest element more than + // fills the screen, since that probably isn't useful. The final zoom cap is + // determined by the minimum zoom of either 2^40x zoom or the necessary zoom + // for the smallest frame to fill the screen three times. + const minWidth = clamp(3 * this.getMinFrameWidth(), maxWidth / maxZoom, maxWidth); + return clamp(viewportWidth, minWidth, maxWidth); + } +} diff --git a/src/speedscope/lib/math.js b/src/speedscope/lib/math.js new file mode 100644 index 0000000000000..5f136c834939d --- /dev/null +++ b/src/speedscope/lib/math.js @@ -0,0 +1,302 @@ +export function clamp(x, minVal, maxVal) { + if (x < minVal) + return minVal; + if (x > maxVal) + return maxVal; + return x; +} +export class Vec2 { + constructor(x, y) { + this.x = x; + this.y = y; + } + withX(x) { + return new Vec2(x, this.y); + } + withY(y) { + return new Vec2(this.x, y); + } + plus(other) { + return new Vec2(this.x + other.x, this.y + other.y); + } + minus(other) { + return new Vec2(this.x - other.x, this.y - other.y); + } + times(scalar) { + return new Vec2(this.x * scalar, this.y * scalar); + } + timesPointwise(other) { + return new Vec2(this.x * other.x, this.y * other.y); + } + dividedByPointwise(other) { + return new Vec2(this.x / other.x, this.y / other.y); + } + dot(other) { + return this.x * other.x + this.y * other.y; + } + equals(other) { + return this.x === other.x && this.y === other.y; + } + approxEquals(other, epsilon = 1e-9) { + return Math.abs(this.x - other.x) < epsilon && Math.abs(this.y - other.y) < epsilon; + } + length2() { + return this.dot(this); + } + length() { + return Math.sqrt(this.length2()); + } + abs() { + return new Vec2(Math.abs(this.x), Math.abs(this.y)); + } + static min(a, b) { + return new Vec2(Math.min(a.x, b.x), Math.min(a.y, b.y)); + } + static max(a, b) { + return new Vec2(Math.max(a.x, b.x), Math.max(a.y, b.y)); + } + static clamp(v, min, max) { + return new Vec2(clamp(v.x, min.x, max.x), clamp(v.y, min.y, max.y)); + } + flatten() { + return [this.x, this.y]; + } +} +Vec2.zero = new Vec2(0, 0); +Vec2.unit = new Vec2(1, 1); +export class AffineTransform { + constructor(m00 = 1, m01 = 0, m02 = 0, m10 = 0, m11 = 1, m12 = 0) { + this.m00 = m00; + this.m01 = m01; + this.m02 = m02; + this.m10 = m10; + this.m11 = m11; + this.m12 = m12; + } + withScale(s) { + let { m00, m01, m02, m10, m11, m12 } = this; + m00 = s.x; + m11 = s.y; + return new AffineTransform(m00, m01, m02, m10, m11, m12); + } + static withScale(s) { + return new AffineTransform().withScale(s); + } + scaledBy(s) { + return AffineTransform.withScale(s).times(this); + } + getScale() { + return new Vec2(this.m00, this.m11); + } + withTranslation(t) { + let { m00, m01, m02, m10, m11, m12 } = this; + m02 = t.x; + m12 = t.y; + return new AffineTransform(m00, m01, m02, m10, m11, m12); + } + static withTranslation(t) { + return new AffineTransform().withTranslation(t); + } + getTranslation() { + return new Vec2(this.m02, this.m12); + } + translatedBy(t) { + return AffineTransform.withTranslation(t).times(this); + } + static betweenRects(from, to) { + return AffineTransform.withTranslation(from.origin.times(-1)) + .scaledBy(new Vec2(to.size.x / from.size.x, to.size.y / from.size.y)) + .translatedBy(to.origin); + } + times(other) { + const m00 = this.m00 * other.m00 + this.m01 * other.m10; + const m01 = this.m00 * other.m01 + this.m01 * other.m11; + const m02 = this.m00 * other.m02 + this.m01 * other.m12 + this.m02; + const m10 = this.m10 * other.m00 + this.m11 * other.m10; + const m11 = this.m10 * other.m01 + this.m11 * other.m11; + const m12 = this.m10 * other.m02 + this.m11 * other.m12 + this.m12; + return new AffineTransform(m00, m01, m02, m10, m11, m12); + } + equals(other) { + return (this.m00 == other.m00 && + this.m01 == other.m01 && + this.m02 == other.m02 && + this.m10 == other.m10 && + this.m11 == other.m11 && + this.m12 == other.m12); + } + approxEquals(other, epsilon = 1e-9) { + return (Math.abs(this.m00 - other.m00) < epsilon && + Math.abs(this.m01 - other.m01) < epsilon && + Math.abs(this.m02 - other.m02) < epsilon && + Math.abs(this.m10 - other.m10) < epsilon && + Math.abs(this.m11 - other.m11) < epsilon && + Math.abs(this.m12 - other.m12) < epsilon); + } + timesScalar(s) { + const { m00, m01, m02, m10, m11, m12 } = this; + return new AffineTransform(s * m00, s * m01, s * m02, s * m10, s * m11, s * m12); + } + det() { + const { m00, m01, m02, m10, m11, m12 } = this; + const m20 = 0; + const m21 = 0; + const m22 = 1; + return (m00 * (m11 * m22 - m12 * m21) - m01 * (m10 * m22 - m12 * m20) + m02 * (m10 * m21 - m11 * m20)); + } + adj() { + const { m00, m01, m02, m10, m11, m12 } = this; + const m20 = 0; + const m21 = 0; + const m22 = 1; + // Adjugate matrix (a) is the transpose of the + // cofactor matrix (c). + // + // 00 01 02 + // 10 11 12 + // 20 21 22 + const a00 = /* c00 = */ +(m11 * m22 - m12 * m21); + const a01 = /* c10 = */ -(m01 * m22 - m02 * m21); + const a02 = /* c20 = */ +(m01 * m12 - m02 * m11); + const a10 = /* c01 = */ -(m10 * m22 - m12 * m20); + const a11 = /* c11 = */ +(m00 * m22 - m02 * m20); + const a12 = /* c21 = */ -(m00 * m12 - m02 * m10); + return new AffineTransform(a00, a01, a02, a10, a11, a12); + } + inverted() { + const det = this.det(); + if (det === 0) + return null; + const adj = this.adj(); + return adj.timesScalar(1 / det); + } + transformVector(v) { + return new Vec2(v.x * this.m00 + v.y * this.m01, v.x * this.m10 + v.y * this.m11); + } + inverseTransformVector(v) { + const inv = this.inverted(); + if (!inv) + return null; + return inv.transformVector(v); + } + transformPosition(v) { + return new Vec2(v.x * this.m00 + v.y * this.m01 + this.m02, v.x * this.m10 + v.y * this.m11 + this.m12); + } + inverseTransformPosition(v) { + const inv = this.inverted(); + if (!inv) + return null; + return inv.transformPosition(v); + } + transformRect(r) { + const size = this.transformVector(r.size); + const origin = this.transformPosition(r.origin); + if (size.x < 0 && size.y < 0) { + return new Rect(origin.plus(size), size.abs()); + } + else if (size.x < 0) { + return new Rect(origin.withX(origin.x + size.x), size.abs()); + } + else if (size.y < 0) { + return new Rect(origin.withY(origin.y + size.y), size.abs()); + } + return new Rect(origin, size); + } + inverseTransformRect(r) { + const inv = this.inverted(); + if (!inv) + return null; + return inv.transformRect(r); + } + flatten() { + // Flatten into GLSL format + // prettier-ignore + return [ + this.m00, this.m10, 0, + this.m01, this.m11, 0, + this.m02, this.m12, 1, + ]; + } +} +export class Rect { + constructor(origin, size) { + this.origin = origin; + this.size = size; + } + isEmpty() { + return this.width() == 0 || this.height() == 0; + } + width() { + return this.size.x; + } + height() { + return this.size.y; + } + left() { + return this.origin.x; + } + right() { + return this.left() + this.width(); + } + top() { + return this.origin.y; + } + bottom() { + return this.top() + this.height(); + } + topLeft() { + return this.origin; + } + topRight() { + return this.origin.plus(new Vec2(this.width(), 0)); + } + bottomRight() { + return this.origin.plus(this.size); + } + bottomLeft() { + return this.origin.plus(new Vec2(0, this.height())); + } + withOrigin(origin) { + return new Rect(origin, this.size); + } + withSize(size) { + return new Rect(this.origin, size); + } + closestPointTo(p) { + return new Vec2(clamp(p.x, this.left(), this.right()), clamp(p.y, this.top(), this.bottom())); + } + distanceFrom(p) { + return p.minus(this.closestPointTo(p)).length(); + } + contains(p) { + return this.distanceFrom(p) === 0; + } + hasIntersectionWith(other) { + const top = Math.max(this.top(), other.top()); + const bottom = Math.max(top, Math.min(this.bottom(), other.bottom())); + if (bottom - top === 0) + return false; + const left = Math.max(this.left(), other.left()); + const right = Math.max(left, Math.min(this.right(), other.right())); + if (right - left === 0) + return false; + return true; + } + intersectWith(other) { + const topLeft = Vec2.max(this.topLeft(), other.topLeft()); + const bottomRight = Vec2.max(topLeft, Vec2.min(this.bottomRight(), other.bottomRight())); + return new Rect(topLeft, bottomRight.minus(topLeft)); + } + equals(other) { + return this.origin.equals(other.origin) && this.size.equals(other.size); + } + approxEquals(other) { + return this.origin.approxEquals(other.origin) && this.size.approxEquals(other.size); + } + area() { + return this.size.x * this.size.y; + } +} +Rect.empty = new Rect(Vec2.zero, Vec2.zero); +Rect.unit = new Rect(Vec2.zero, Vec2.unit); +Rect.NDC = new Rect(new Vec2(-1, -1), new Vec2(2, 2)); diff --git a/src/speedscope/lib/profile.js b/src/speedscope/lib/profile.js new file mode 100644 index 0000000000000..e66ffbd023f20 --- /dev/null +++ b/src/speedscope/lib/profile.js @@ -0,0 +1,514 @@ +import {lastOf, KeyedSet} from './utils' +import {ValueFormatter, RawValueFormatter} from './value-formatters' +import {FileFormat} from './file-format-spec' +const demangleCppModule = import('./demangle-cpp') + +// Force eager loading of the module +demangleCppModule.then(() => {}) + +export class HasWeights { + constructor() { + this.selfWeight = 0; + this.totalWeight = 0; + } + getSelfWeight() { + return this.selfWeight; + } + getTotalWeight() { + return this.totalWeight; + } + addToTotalWeight(delta) { + this.totalWeight += delta; + } + addToSelfWeight(delta) { + this.selfWeight += delta; + } + overwriteWeightWith(other) { + this.selfWeight = other.selfWeight; + this.totalWeight = other.totalWeight; + } +} +export class Frame extends HasWeights { + constructor(info) { + super(); + this.key = info.key; + this.name = info.name; + this.file = info.file; + this.line = info.line; + this.col = info.col; + } + static getOrInsert(set, info) { + return set.getOrInsert(new Frame(info)); + } +} +Frame.root = new Frame({ + key: '(speedscope root)', + name: '(speedscope root)', +}); +export class CallTreeNode extends HasWeights { + constructor(frame, parent) { + super(); + this.frame = frame; + this.parent = parent; + this.children = []; + // If a node is "frozen", it means it should no longer be mutated. + this.frozen = false; + } + isRoot() { + return this.frame === Frame.root; + } + isFrozen() { + return this.frozen; + } + freeze() { + this.frozen = true; + } +} +export class Profile { + constructor(totalWeight = 0) { + this.name = ''; + this.frames = new KeyedSet(); + this.appendOrderCalltreeRoot = new CallTreeNode(Frame.root, null); + this.groupedCalltreeRoot = new CallTreeNode(Frame.root, null); + // List of references to CallTreeNodes at the top of the + // stack at the time of the sample. + this.samples = []; + this.weights = []; + this.valueFormatter = new RawValueFormatter(); + this.totalNonIdleWeight = null; + this.totalWeight = totalWeight; + } + getAppendOrderCalltreeRoot() { + return this.appendOrderCalltreeRoot; + } + getGroupedCalltreeRoot() { + return this.groupedCalltreeRoot; + } + formatValue(v) { + return this.valueFormatter.format(v); + } + setValueFormatter(f) { + this.valueFormatter = f; + } + getWeightUnit() { + return this.valueFormatter.unit; + } + getName() { + return this.name; + } + setName(name) { + this.name = name; + } + getTotalWeight() { + return this.totalWeight; + } + getTotalNonIdleWeight() { + if (this.totalNonIdleWeight === null) { + this.totalNonIdleWeight = this.groupedCalltreeRoot.children.reduce((n, c) => n + c.getTotalWeight(), 0); + } + return this.totalNonIdleWeight; + } + forEachCallGrouped(openFrame, closeFrame) { + function visit(node, start) { + if (node.frame !== Frame.root) { + openFrame(node, start); + } + let childTime = 0; + const children = [...node.children]; + children.sort((a, b) => (a.getTotalWeight() > b.getTotalWeight() ? -1 : 1)); + children.forEach(function (child) { + visit(child, start + childTime); + childTime += child.getTotalWeight(); + }); + if (node.frame !== Frame.root) { + closeFrame(node, start + node.getTotalWeight()); + } + } + visit(this.groupedCalltreeRoot, 0); + } + forEachCall(openFrame, closeFrame) { + let prevStack = []; + let value = 0; + let sampleIndex = 0; + for (let stackTop of this.samples) { + // Find lowest common ancestor of the current stack and the previous one + let lca = null; + // This is O(n^2), but n should be relatively small here (stack height), + // so hopefully this isn't much of a problem + for (lca = stackTop; lca && lca.frame != Frame.root && prevStack.indexOf(lca) === -1; lca = lca.parent) { } + // Close frames that are no longer open + while (prevStack.length > 0 && lastOf(prevStack) != lca) { + const node = prevStack.pop(); + closeFrame(node, value); + } + // Open frames that are now becoming open + const toOpen = []; + for (let node = stackTop; node && node.frame != Frame.root && node != lca; node = node.parent) { + toOpen.push(node); + } + toOpen.reverse(); + for (let node of toOpen) { + openFrame(node, value); + } + prevStack = prevStack.concat(toOpen); + value += this.weights[sampleIndex++]; + } + // Close frames that are open at the end of the trace + for (let i = prevStack.length - 1; i >= 0; i--) { + closeFrame(prevStack[i], value); + } + } + forEachFrame(fn) { + this.frames.forEach(fn); + } + forEachSample(fn) { + for (let i = 0; i < this.samples.length; i++) { + fn(this.samples[i], this.weights[i]); + } + } + getProfileWithRecursionFlattened() { + const builder = new CallTreeProfileBuilder(); + const stack = []; + const framesInStack = new Set(); + function openFrame(node, value) { + if (framesInStack.has(node.frame)) { + stack.push(null); + } + else { + framesInStack.add(node.frame); + stack.push(node); + builder.enterFrame(node.frame, value); + } + } + function closeFrame(node, value) { + const stackTop = stack.pop(); + if (stackTop) { + framesInStack.delete(stackTop.frame); + builder.leaveFrame(stackTop.frame, value); + } + } + this.forEachCall(openFrame, closeFrame); + const flattenedProfile = builder.build(); + flattenedProfile.name = this.name; + flattenedProfile.valueFormatter = this.valueFormatter; + // When constructing a profile with recursion flattened, + // counter-intuitive things can happen to "self time" measurements + // for functions. + // For example, given the following list of stacks w/ weights: + // + // a 1 + // a;b;a 1 + // a;b;a;b;a 1 + // a;b;a 1 + // + // The resulting profile with recursion flattened out will look like this: + // + // a 1 + // a;b 3 + // + // Which is useful to view, but it's counter-intuitive to move self-time + // for frames around, since analyzing the self-time of functions is an important + // thing to be able to do accurately, and we don't want this to change when recursion + // is flattened. To work around that, we'll just copy the weights directly from the + // un-flattened profile. + this.forEachFrame(f => { + flattenedProfile.frames.getOrInsert(f).overwriteWeightWith(f); + }); + return flattenedProfile; + } + getInvertedProfileForCallersOf(focalFrameInfo) { + const focalFrame = Frame.getOrInsert(this.frames, focalFrameInfo); + const builder = new StackListProfileBuilder(); + // TODO(jlfwong): Could construct this at profile + // construction time rather than on demand. + const nodes = []; + function visit(node) { + if (node.frame === focalFrame) { + nodes.push(node); + } + else { + for (let child of node.children) { + visit(child); + } + } + } + visit(this.appendOrderCalltreeRoot); + for (let node of nodes) { + const stack = []; + for (let n = node; n != null && n.frame !== Frame.root; n = n.parent) { + stack.push(n.frame); + } + builder.appendSampleWithWeight(stack, node.getTotalWeight()); + } + const ret = builder.build(); + ret.name = this.name; + ret.valueFormatter = this.valueFormatter; + return ret; + } + getProfileForCalleesOf(focalFrameInfo) { + const focalFrame = Frame.getOrInsert(this.frames, focalFrameInfo); + const builder = new StackListProfileBuilder(); + function recordSubtree(focalFrameNode) { + const stack = []; + function visit(node) { + stack.push(node.frame); + builder.appendSampleWithWeight(stack, node.getSelfWeight()); + for (let child of node.children) { + visit(child); + } + stack.pop(); + } + visit(focalFrameNode); + } + function findCalls(node) { + if (node.frame === focalFrame) { + recordSubtree(node); + } + else { + for (let child of node.children) { + findCalls(child); + } + } + } + findCalls(this.appendOrderCalltreeRoot); + const ret = builder.build(); + ret.name = this.name; + ret.valueFormatter = this.valueFormatter; + return ret; + } + // Demangle symbols for readability + async demangle() { + let demangleCpp = null; + for (let frame of this.frames) { + // This function converts a mangled C++ name such as "__ZNK7Support6ColorFeqERKS0_" + // into a human-readable symbol (in this case "Support::ColorF::==(Support::ColorF&)") + if (frame.name.startsWith('__Z')) { + if (!demangleCpp) { + demangleCpp = (await demangleCppModule).demangleCpp; + } + frame.name = demangleCpp(frame.name); + } + } + } + remapNames(callback) { + for (let frame of this.frames) { + frame.name = callback(frame.name); + } + } +} +export class StackListProfileBuilder extends Profile { + constructor() { + super(...arguments); + this.pendingSample = null; + } + _appendSample(stack, weight, useAppendOrder) { + if (isNaN(weight)) + throw new Error('invalid weight'); + let node = useAppendOrder ? this.appendOrderCalltreeRoot : this.groupedCalltreeRoot; + let framesInStack = new Set(); + for (let frameInfo of stack) { + const frame = Frame.getOrInsert(this.frames, frameInfo); + const last = useAppendOrder + ? lastOf(node.children) + : node.children.find(c => c.frame === frame); + if (last && !last.isFrozen() && last.frame == frame) { + node = last; + } + else { + const parent = node; + node = new CallTreeNode(frame, node); + parent.children.push(node); + } + node.addToTotalWeight(weight); + // It's possible for the same frame to occur multiple + // times in the same call stack due to either direct + // or indirect recursion. We want to avoid counting that + // frame multiple times for a single sample, we so just + // track all of the unique frames that participated in + // this call stack, then add to their weight at the end. + framesInStack.add(node.frame); + } + node.addToSelfWeight(weight); + if (useAppendOrder) { + for (let child of node.children) { + child.freeze(); + } + } + if (useAppendOrder) { + node.frame.addToSelfWeight(weight); + for (let frame of framesInStack) { + frame.addToTotalWeight(weight); + } + if (node === lastOf(this.samples)) { + this.weights[this.weights.length - 1] += weight; + } + else { + this.samples.push(node); + this.weights.push(weight); + } + } + } + appendSampleWithWeight(stack, weight) { + if (weight === 0) { + // Samples with zero weight have no effect, so let's ignore them + return; + } + if (weight < 0) { + throw new Error('Samples must have positive weights'); + } + this._appendSample(stack, weight, true); + this._appendSample(stack, weight, false); + } + appendSampleWithTimestamp(stack, timestamp) { + if (this.pendingSample) { + if (timestamp < this.pendingSample.centralTimestamp) { + throw new Error('Timestamps received out of order'); + } + const endTimestamp = (timestamp + this.pendingSample.centralTimestamp) / 2; + this.appendSampleWithWeight(this.pendingSample.stack, endTimestamp - this.pendingSample.startTimestamp); + this.pendingSample = { stack, startTimestamp: endTimestamp, centralTimestamp: timestamp }; + } + else { + this.pendingSample = { stack, startTimestamp: timestamp, centralTimestamp: timestamp }; + } + } + build() { + if (this.pendingSample) { + if (this.samples.length > 0) { + this.appendSampleWithWeight(this.pendingSample.stack, this.pendingSample.centralTimestamp - this.pendingSample.startTimestamp); + } + else { + // There is only a single sample. In this case, units will be meaningless, + // so we'll append with a weight of 1 and also clear any value formatter + this.appendSampleWithWeight(this.pendingSample.stack, 1); + this.setValueFormatter(new RawValueFormatter()); + } + } + this.totalWeight = Math.max(this.totalWeight, this.weights.reduce((a, b) => a + b, 0)); + return this; + } +} +// As an alternative API for importing profiles more efficiently, provide a +// way to open & close frames directly without needing to construct tons of +// arrays as intermediaries. +export class CallTreeProfileBuilder extends Profile { + constructor() { + super(...arguments); + this.appendOrderStack = [this.appendOrderCalltreeRoot]; + this.groupedOrderStack = [this.groupedCalltreeRoot]; + this.framesInStack = new Map(); + this.stack = []; + this.lastValue = 0; + } + addWeightsToFrames(value) { + const delta = value - this.lastValue; + for (let frame of this.framesInStack.keys()) { + frame.addToTotalWeight(delta); + } + const stackTop = lastOf(this.stack); + if (stackTop) { + stackTop.addToSelfWeight(delta); + } + } + addWeightsToNodes(value, stack) { + const delta = value - this.lastValue; + for (let node of stack) { + node.addToTotalWeight(delta); + } + const stackTop = lastOf(stack); + if (stackTop) { + stackTop.addToSelfWeight(delta); + } + } + _enterFrame(frame, value, useAppendOrder) { + let stack = useAppendOrder ? this.appendOrderStack : this.groupedOrderStack; + this.addWeightsToNodes(value, stack); + let prevTop = lastOf(stack); + if (prevTop) { + if (useAppendOrder) { + const delta = value - this.lastValue; + if (delta > 0) { + this.samples.push(prevTop); + this.weights.push(value - this.lastValue); + } + else if (delta < 0) { + throw new Error(`Samples must be provided in increasing order of cumulative value. Last sample was ${this.lastValue}, this sample was ${value}`); + } + } + const last = useAppendOrder + ? lastOf(prevTop.children) + : prevTop.children.find(c => c.frame === frame); + let node; + if (last && !last.isFrozen() && last.frame == frame) { + node = last; + } + else { + node = new CallTreeNode(frame, prevTop); + prevTop.children.push(node); + } + stack.push(node); + } + } + enterFrame(frameInfo, value) { + const frame = Frame.getOrInsert(this.frames, frameInfo); + this.addWeightsToFrames(value); + this._enterFrame(frame, value, true); + this._enterFrame(frame, value, false); + this.stack.push(frame); + const frameCount = this.framesInStack.get(frame) || 0; + this.framesInStack.set(frame, frameCount + 1); + this.lastValue = value; + } + _leaveFrame(frame, value, useAppendOrder) { + let stack = useAppendOrder ? this.appendOrderStack : this.groupedOrderStack; + this.addWeightsToNodes(value, stack); + if (useAppendOrder) { + const leavingStackTop = this.appendOrderStack.pop(); + if (leavingStackTop == null) { + throw new Error(`Trying to leave ${frame.key} when stack is empty`); + } + if (this.lastValue == null) { + throw new Error(`Trying to leave a ${frame.key} before any have been entered`); + } + leavingStackTop.freeze(); + const delta = value - this.lastValue; + if (delta > 0) { + this.samples.push(leavingStackTop); + this.weights.push(value - this.lastValue); + } + else if (delta < 0) { + throw new Error(`Samples must be provided in increasing order of cumulative value. Last sample was ${this + .lastValue}, this sample was ${value}`); + } + } + else { + this.groupedOrderStack.pop(); + } + } + leaveFrame(frameInfo, value) { + const frame = Frame.getOrInsert(this.frames, frameInfo); + this.addWeightsToFrames(value); + this._leaveFrame(frame, value, true); + this._leaveFrame(frame, value, false); + this.stack.pop(); + const frameCount = this.framesInStack.get(frame); + if (frameCount == null) + return; + if (frameCount === 1) { + this.framesInStack.delete(frame); + } + else { + this.framesInStack.set(frame, frameCount - 1); + } + this.lastValue = value; + this.totalWeight = Math.max(this.totalWeight, this.lastValue); + } + build() { + // Each stack is expected to contain a single node which we initialize to be + // the root node. + if (this.appendOrderStack.length > 1 || this.groupedOrderStack.length > 1) { + throw new Error('Tried to complete profile construction with a non-empty stack'); + } + return this; + } +} diff --git a/src/speedscope/lib/utils.js b/src/speedscope/lib/utils.js new file mode 100644 index 0000000000000..e1923f8a10d29 --- /dev/null +++ b/src/speedscope/lib/utils.js @@ -0,0 +1,254 @@ +export function lastOf(ts) { + return ts[ts.length - 1] || null; +} +export function sortBy(ts, key) { + function comparator(a, b) { + return key(a) < key(b) ? -1 : 1; + } + ts.sort(comparator); +} +export function getOrInsert(map, k, fallback) { + if (!map.has(k)) + map.set(k, fallback(k)); + return map.get(k); +} +export function getOrElse(map, k, fallback) { + if (!map.has(k)) + return fallback(k); + return map.get(k); +} +export function getOrThrow(map, k) { + if (!map.has(k)) { + throw new Error(`Expected key ${k}`); + } + return map.get(k); +} +export class KeyedSet { + constructor() { + this.map = new Map(); + } + getOrInsert(t) { + const key = t.key; + const existing = this.map.get(key); + if (existing) + return existing; + this.map.set(key, t); + return t; + } + forEach(fn) { + this.map.forEach(fn); + } + [Symbol.iterator]() { + return this.map.values(); + } +} +export function* itMap(it, f) { + for (let t of it) { + yield f(t); + } +} +export function itForEach(it, f) { + for (let t of it) { + f(t); + } +} +export function itReduce(it, f, init) { + let accum = init; + for (let t of it) { + accum = f(accum, t); + } + return accum; +} +export function zeroPad(s, width) { + return new Array(Math.max(width - s.length, 0) + 1).join('0') + s; +} +export function formatPercent(percent) { + let formattedPercent = `${percent.toFixed(0)}%`; + if (percent === 100) + formattedPercent = '100%'; + else if (percent > 99) + formattedPercent = '>99%'; + else if (percent < 0.01) + formattedPercent = '<0.01%'; + else if (percent < 1) + formattedPercent = `${percent.toFixed(2)}%`; + else if (percent < 10) + formattedPercent = `${percent.toFixed(1)}%`; + return formattedPercent; +} +export function fract(x) { + return x - Math.floor(x); +} +export function triangle(x) { + return 2.0 * Math.abs(fract(x) - 0.5) - 1.0; +} +export function binarySearch(lo, hi, f, target, targetRangeSize = 1) { + console.assert(!isNaN(targetRangeSize) && !isNaN(target)); + while (true) { + if (hi - lo <= targetRangeSize) + return [lo, hi]; + const mid = (hi + lo) / 2; + const val = f(mid); + if (val < target) + lo = mid; + else + hi = mid; + } +} +export function noop(...args) { } +export function objectsHaveShallowEquality(a, b) { + for (let key in a) { + if (a[key] !== b[key]) + return false; + } + for (let key in b) { + if (a[key] !== b[key]) + return false; + } + return true; +} +export function memoizeByShallowEquality(cb) { + let last = null; + return (args) => { + let result; + if (last == null) { + result = cb(args); + last = { args, result }; + return result; + } + else if (objectsHaveShallowEquality(last.args, args)) { + return last.result; + } + else { + last.args = args; + last.result = cb(args); + return last.result; + } + }; +} +export function memoizeByReference(cb) { + let last = null; + return (args) => { + let result; + if (last == null) { + result = cb(args); + last = { args, result }; + return result; + } + else if (last.args === args) { + return last.result; + } + else { + last.args = args; + last.result = cb(args); + return last.result; + } + }; +} +export function lazyStatic(cb) { + let last = null; + return () => { + if (last == null) { + last = { result: cb() }; + } + return last.result; + }; +} +const base64lookupTable = lazyStatic(() => { + const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + const ret = new Map(); + for (let i = 0; i < alphabet.length; i++) { + ret.set(alphabet.charAt(i), i); + } + ret.set('=', -1); + return ret; +}); +// NOTE: There are probably simpler solutions to this problem, but I have this written already, so +// until we run into problems with this, let's just use this. +// +// See: https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#The_Unicode_Problem#The_Unicode_Problem +export function decodeBase64(encoded) { + // Reference: https://www.rfc-editor.org/rfc/rfc4648.txt + const lookupTable = base64lookupTable(); + // 3 byte groups are represented as sequneces of 4 characters. + // + // "The encoding process represents 24-bit groups of input bits as output + // strings of 4 encoded characters." + // + // "Special processing is performed if fewer than 24 bits are available + // at the end of the data being encoded. A full encoding quantum is + // always completed at the end of a quantity. When fewer than 24 input + // bits are available in an input group bits with value zero are added + // (on the right) to form an integral number of 6-bit groups." + if (encoded.length % 4 !== 0) { + throw new Error(`Invalid length for base64 encoded string. Expected length % 4 = 0, got length = ${encoded.length}`); + } + const quartetCount = encoded.length / 4; + let byteCount; + // Special processing is performed if fewer than 24 bits are available + // at the end of the data being encoded. A full encoding quantum is + // always completed at the end of a quantity. When fewer than 24 input + // bits are available in an input group, bits with value zero are added + // (on the right) to form an integral number of 6-bit groups. Padding + // at the end of the data is performed using the '=' character. Since + // all base 64 input is an integral number of octets, only the following + // cases can arise: + // + // (1) The final quantum of encoding input is an integral multiple of 24 + // bits; here, the final unit of encoded output will be an integral + // multiple of 4 characters with no "=" padding. + // + // (2) The final quantum of encoding input is exactly 8 bits; here, the + // final unit of encoded output will be two characters followed by + // two "=" padding characters. + // + // (3) The final quantum of encoding input is exactly 16 bits; here, the + // final unit of encoded output will be three characters followed by + // one "=" padding character. + if (encoded.length >= 4) { + if (encoded.charAt(encoded.length - 1) === '=') { + if (encoded.charAt(encoded.length - 2) === '=') { + // Case (2) + byteCount = quartetCount * 3 - 2; + } + else { + // Case (3) + byteCount = quartetCount * 3 - 1; + } + } + else { + // Case (1) + byteCount = quartetCount * 3; + } + } + else { + // Case (1) + byteCount = quartetCount * 3; + } + const bytes = new Uint8Array(byteCount); + let offset = 0; + for (let i = 0; i < quartetCount; i++) { + const enc1 = encoded.charAt(i * 4 + 0); + const enc2 = encoded.charAt(i * 4 + 1); + const enc3 = encoded.charAt(i * 4 + 2); + const enc4 = encoded.charAt(i * 4 + 3); + const sextet1 = lookupTable.get(enc1); + const sextet2 = lookupTable.get(enc2); + const sextet3 = lookupTable.get(enc3); + const sextet4 = lookupTable.get(enc4); + if (sextet1 == null || sextet2 == null || sextet3 == null || sextet4 == null) { + throw new Error(`Invalid quartet at indices ${i * 4} .. ${i * 4 + 3}: ${encoded.substring(i * 4, i * 4 + 3)}`); + } + bytes[offset++] = (sextet1 << 2) | (sextet2 >> 4); + if (enc3 !== '=') { + bytes[offset++] = ((sextet2 & 15) << 4) | (sextet3 >> 2); + } + if (enc4 !== '=') { + bytes[offset++] = ((sextet3 & 7) << 6) | sextet4; + } + } + if (offset !== byteCount) { + throw new Error(`Expected to decode ${byteCount} bytes, but only decoded ${offset})`); + } + return bytes; +} diff --git a/src/speedscope/lib/value-formatters.js b/src/speedscope/lib/value-formatters.js new file mode 100644 index 0000000000000..089b490a6af0c --- /dev/null +++ b/src/speedscope/lib/value-formatters.js @@ -0,0 +1,59 @@ +import {zeroPad} from './utils'; + +export class RawValueFormatter { + constructor() { + this.unit = 'none'; + } + format(v) { + return v.toLocaleString(); + } +} +export class TimeFormatter { + constructor(unit) { + this.unit = unit; + if (unit === 'nanoseconds') + this.multiplier = 1e-9; + else if (unit === 'microseconds') + this.multiplier = 1e-6; + else if (unit === 'milliseconds') + this.multiplier = 1e-3; + else + this.multiplier = 1; + } + formatUnsigned(v) { + const s = v * this.multiplier; + if (s / 60 >= 1) { + const minutes = Math.floor(s / 60); + const seconds = Math.floor(s - minutes * 60).toString(); + return `${minutes}:${zeroPad(seconds, 2)}`; + } + if (s / 1 >= 1) + return `${s.toFixed(2)}s`; + if (s / 1e-3 >= 1) + return `${(s / 1e-3).toFixed(2)}ms`; + if (s / 1e-6 >= 1) + return `${(s / 1e-6).toFixed(2)}µs`; + else + return `${(s / 1e-9).toFixed(2)}ns`; + } + format(v) { + return `${v < 0 ? '-' : ''}${this.formatUnsigned(Math.abs(v))}`; + } +} +export class ByteFormatter { + constructor() { + this.unit = 'bytes'; + } + format(v) { + if (v < 1024) + return `${v.toFixed(0)} B`; + v /= 1024; + if (v < 1024) + return `${v.toFixed(2)} KB`; + v /= 1024; + if (v < 1024) + return `${v.toFixed(2)} MB`; + v /= 1024; + return `${v.toFixed(2)} GB`; + } +} diff --git a/src/tracerbench/trace/bounds.js b/src/tracerbench/trace/bounds.js new file mode 100644 index 0000000000000..f2ff80746f655 --- /dev/null +++ b/src/tracerbench/trace/bounds.js @@ -0,0 +1,27 @@ +import { TRACE_EVENT_PHASE_COMPLETE, TRACE_EVENT_PHASE_METADATA } from './trace_event'; +export default class Bounds { + constructor() { + this.min = 0; + this.max = 0; + this.empty = true; + } + addValue(value) { + if (this.empty) { + this.empty = false; + this.min = this.max = value; + } + else { + this.max = Math.max(this.max, value); + this.min = Math.min(this.min, value); + } + } + addEvent(event) { + if (event.ph === TRACE_EVENT_PHASE_METADATA) { + return; + } + this.addValue(event.ts); + if (event.ph === TRACE_EVENT_PHASE_COMPLETE) { + this.addValue(event.ts + event.dur); + } + } +} diff --git a/src/tracerbench/trace/cpu-profile.js b/src/tracerbench/trace/cpu-profile.js new file mode 100644 index 0000000000000..4b766e3a59df3 --- /dev/null +++ b/src/tracerbench/trace/cpu-profile.js @@ -0,0 +1,316 @@ +import { hierarchy } from 'd3-hierarchy'; +import { addRenderNodes } from './render-events'; +import { FUNCTION_NAME, TRACE_EVENT_NAME, TRACE_EVENT_PHASE_BEGIN, TRACE_EVENT_PHASE_END, TRACE_EVENT_PHASE_COMPLETE } from './trace_event'; +export default class CpuProfile { + constructor(profile, events, min, max) { + this.profile = profile; + const parentLinks = (this.parentLinks = new Map()); + const childrenLinks = (this.childrenLinks = new Map()); + const nodes = profile.nodes; + initNodes(nodes); + const nodeMap = mapAndLinkNodes(nodes, parentLinks, childrenLinks); + const originalRoot = nodes.find(node => { + return (node.callFrame.scriptId === 0 || + (node.callFrame.scriptId === '0' && + node.callFrame.functionName === FUNCTION_NAME.ROOT)); + }); + if (originalRoot === undefined) { + throw new Error('Missing root node in original profile'); + } + this.samples = absoluteSamples(profile, nodeMap); + const { expandedRoot, expandedNodeMap } = expandAndFix(this.samples, profile, events, min, max, parentLinks, childrenLinks, originalRoot); + this.root = expandedRoot; + this.nodeMap = expandedNodeMap; + const start = (this.start = profile.startTime); + const end = (this.end = expandedRoot.max); + this.duration = end - start; + this.hierarchy = hierarchy(expandedRoot, node => { + const children = childrenLinks.get(node); + if (children) { + return expandedRoot === node + ? children.filter(n => !isMetaNode(n)) + : children; + } + return null; + }); + // Make child iteration easier + this.hierarchy.each(node => { + if (node.children === undefined) { + node.children = []; + } + }); + addRenderNodes(this.hierarchy, events); + } + parent(node) { + return this.parentLinks.get(node); + } + children(node) { + return this.childrenLinks.get(node); + } + node(id) { + const n = this.nodeMap.get(id); + if (n === undefined) { + throw new Error(`invalid node id: ${id}`); + } + return n; + } +} +export function getChildren(node) { + if (node.children === undefined) { + throw new Error('Node had undefined children'); + } + return node.children; +} +function expandAndFix(samples, profile, events, min, max, parentLinks, childrenLinks, root) { + const { expandedNodes, orig2ExpNodes } = expandNodes(samples, events, min, max, parentLinks); + profile.nodes = expandedNodes; + parentLinks.clear(); + childrenLinks.clear(); + const expandedNodeMap = mapAndLinkNodes(expandedNodes, parentLinks, childrenLinks); + if (!orig2ExpNodes.has(root.id)) { + throw new Error('Missing root node in expanded profile'); + } + return { expandedRoot: orig2ExpNodes.get(root.id)[0], expandedNodeMap }; +} +function initNodes(nodes) { + for (let i = 0; i < nodes.length; i++) { + const node = nodes[i]; + // initialize our extensions + node.min = -1; + node.max = -1; + node.sampleCount = 0; + node.self = 0; + } +} +function mapAndLinkNodes(nodes, parentLinks, childrenLinks) { + const nodeMap = new Map(); + for (let i = 0; i < nodes.length; i++) { + nodeMap.set(nodes[i].id, nodes[i]); + } + linkNodes(nodes, nodeMap, parentLinks, childrenLinks); + return nodeMap; +} +function linkNodes(nodes, nodeMap, parentLinks, childrenLinks) { + for (let i = 0; i < nodes.length; i++) { + const node = nodes[i]; + linkChildren(node, nodeMap, parentLinks, childrenLinks); + } +} +function linkChildren(parent, nodeMap, parentLinks, childrenLinks) { + const childIds = parent.children; + if (childIds === undefined) { + return; + } + const children = new Array(childIds.length); + for (let i = 0; i < childIds.length; i++) { + const child = nodeMap.get(childIds[i]); + children[i] = child; + parentLinks.set(child, parent); + } + childrenLinks.set(parent, children); +} +function absoluteSamples(profile, nodeMap) { + const sampleIds = profile.samples; + const samples = new Array(sampleIds.length); + // deltas can be negative and samples out of order + const timeDeltas = profile.timeDeltas; + let last = profile.startTime; + for (let i = 0; i < sampleIds.length; i++) { + const node = nodeMap.get(sampleIds[i]); + const timestamp = last + timeDeltas[i]; + samples[i] = { + node, + delta: 0, + timestamp, + prev: null, + next: null, + }; + last = timestamp; + node.sampleCount++; + } + samples.sort((a, b) => a.timestamp - b.timestamp); + let prev = null; + for (let i = 0; i < samples.length; i++) { + const sample = samples[i]; + const timestamp = sample.timestamp; + if (prev === null) { + sample.delta = timestamp - profile.startTime; + } + else { + prev.next = sample; + sample.delta = timestamp - prev.timestamp; + sample.prev = prev; + } + prev = sample; + } + return samples; +} +function expandNodes(samples, events, min, max, parentLinks) { + const expandedNodes = []; + const orig2ExpNodes = new Map(); + const state = { + lastSampleTS: -1, + stack: [], + origId2activeIndex: new Map(), + expId2origId: new Map(), + }; + let begin; + let from = -1; + let to = -1; + let sampleIndex = 0; + let eventIndex = 0; + while (sampleIndex < samples.length) { + // move through events until we have an executing range + for (; eventIndex < events.length; eventIndex++) { + const event = events[eventIndex]; + if (begin !== undefined) { + if (event.ph === TRACE_EVENT_PHASE_END && + event.pid === begin.pid && + event.tid === begin.tid && + event.cat === begin.cat && + event.name === begin.name) { + begin = undefined; + to = event.ts; + } + } + else if (from === -1) { + if (event.name === TRACE_EVENT_NAME.V8_EXECUTE) { + if (event.ph === TRACE_EVENT_PHASE_BEGIN) { + begin = event; + from = event.ts; + to = -1; + } + else if (event.ph === TRACE_EVENT_PHASE_COMPLETE) { + from = event.ts; + to = event.ts + event.dur; + } + } + } + else if (event.ts > to) { + break; + } + } + // we should be just after `to` or out of events + // if we don't have a from/to then this will drain + // samples and exit + for (; sampleIndex < samples.length; sampleIndex++) { + // process samples in execute range + const sample = samples[sampleIndex]; + if (to !== -1 && sample.timestamp > to) { + // end executing + endExecute(state, to); + from = to = -1; + break; + } + else if (from !== -1 && + sample.timestamp > from && + !isOutOfBounds(sample.timestamp, min, max)) { + processSample(sample, orig2ExpNodes, parentLinks, expandedNodes, state); + } + } + // we should be just past a range or have no more samples + } + if (to !== -1) { + endExecute(state, to); + } + terminateNodes(state.stack, state.lastSampleTS, state); + return { expandedNodes, orig2ExpNodes }; +} +function isOutOfBounds(ts, min, max) { + return ts < min || (max !== -1 && ts > max); +} +function terminateNodes(toTerminate, ts, state) { + toTerminate.forEach(node => { + state.origId2activeIndex.delete(state.expId2origId.get(node.id)); + state.expId2origId.delete(node.id); + node.max = ts; + }); +} +function activateNodes(toActivate, state, ts, newNodes, orig2ExpNodes) { + const { stack, origId2activeIndex, expId2origId } = state; + let parent = stack[stack.length - 1]; + for (let i = toActivate.length - 1; i >= 0; i--) { + const oldNode = toActivate[i]; + // IProfileNode type gives access to the .parent attribute + const newNode = JSON.parse(JSON.stringify(oldNode)); + newNode.id = newNodes.length; + if (parent) { + newNode.parent = parent.id; + const children = parent.children; + if (children !== undefined) { + children.push(newNode.id); + } + else { + parent.children = [newNode.id]; + } + } + // clear out node-->children links + newNode.children = undefined; + newNode.min = ts; + newNode.max = -1; + newNode.self = 0; + newNode.total = 0; + newNodes.push(newNode); + stack.push(newNode); + origId2activeIndex.set(oldNode.id, stack.length - 1); + expId2origId.set(newNode.id, oldNode.id); + if (orig2ExpNodes.has(oldNode.id)) { + orig2ExpNodes.get(oldNode.id).push(newNode); + } + else { + orig2ExpNodes.set(oldNode.id, [newNode]); + } + parent = newNode; + } +} +function addDurationToNodes(stack, delta) { + if (stack.length > 0) { + stack[stack.length - 1].self += delta; + } +} +function endExecute(state, timestamp) { + const { stack, lastSampleTS } = state; + addDurationToNodes(stack, timestamp - lastSampleTS); + const toTerminate = stack.splice(1); // don't slice (root) + terminateNodes(toTerminate, timestamp, state); +} +function processSample(sample, orig2ExpNodes, parentLinks, newNodes, state) { + const { stack, origId2activeIndex } = state; + let curNode; + const toActivate = []; + state.lastSampleTS = sample.timestamp; + for (curNode = sample.node; curNode; curNode = parentLinks.get(curNode)) { + if (origId2activeIndex.has(curNode.id)) { + break; + } + toActivate.push(curNode); + } + addDurationToNodes(stack, sample.delta); + let spliceStart; + if (curNode === undefined) { + // No ongoing nodes, remove everything from the stack + spliceStart = 0; + } + else { + // Don't let GC or Program samples terminate the current stack + if (sample.node.callFrame.functionName === FUNCTION_NAME.GC || + sample.node.callFrame.functionName === FUNCTION_NAME.PROGRAM) { + spliceStart = stack.length; // no-op for slice + } + else { + // Leave only ongoing nodes on the stack + spliceStart = origId2activeIndex.get(curNode.id) + 1; + } + } + const toTerminate = stack.splice(spliceStart); + terminateNodes(toTerminate, sample.timestamp, state); + activateNodes(toActivate, state, sample.timestamp, newNodes, orig2ExpNodes); +} +export function isMetaNode(node) { + switch (node.callFrame.functionName) { + case FUNCTION_NAME.ROOT: + case FUNCTION_NAME.IDLE: + return true; + } + return false; +} diff --git a/src/tracerbench/trace/index.js b/src/tracerbench/trace/index.js new file mode 100644 index 0000000000000..13724dd8a6056 --- /dev/null +++ b/src/tracerbench/trace/index.js @@ -0,0 +1,11 @@ +export { default as Bounds } from './bounds'; +export { default as Process } from './process'; +export { default as Trace } from './trace'; +export { default as Thread } from './thread'; +export { analyze, IAnalyze } from './analyze'; +export * from './archive_trace'; +export { loadTrace } from './load_trace'; +export { liveTrace } from './live_trace'; +export { networkConditions, IConditions, INetworkConditions, } from './conditions'; +export * from './trace_event'; +export { getBrowserArgs } from './utils'; diff --git a/src/tracerbench/trace/process.js b/src/tracerbench/trace/process.js new file mode 100644 index 0000000000000..209f83f136c81 --- /dev/null +++ b/src/tracerbench/trace/process.js @@ -0,0 +1,26 @@ +import Bounds from './bounds'; +import Thread from './thread'; +export default class Process { + constructor(id) { + this.id = id; + this.threads = []; + this.mainThread = null; + this.scriptStreamerThread = null; + this.bounds = new Bounds(); + this.events = []; + this.threadMap = {}; + } + thread(tid) { + let thread = this.threadMap[tid]; + if (thread === undefined) { + this.threadMap[tid] = thread = new Thread(tid); + this.threads.push(thread); + } + return thread; + } + addEvent(event) { + this.bounds.addEvent(event); + this.events.push(event); + this.thread(event.tid).addEvent(event); + } +} diff --git a/src/tracerbench/trace/render-events.js b/src/tracerbench/trace/render-events.js new file mode 100644 index 0000000000000..92af1b68b3765 --- /dev/null +++ b/src/tracerbench/trace/render-events.js @@ -0,0 +1,138 @@ +import binsearch from 'array-binsearch'; +import { getChildren } from './cpu-profile'; +import { TRACE_EVENT_PHASE_COMPLETE, TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN, } from './trace_event'; +const cloneDeep = require('lodash.clonedeep'); +export function addRenderNodes(hierarchy, events) { + events.forEach(event => { + if (!isRenderPhase(event)) { + return; + } + let found = null; + // Search for the closest node which fully encloses the render event + hierarchy.eachBefore((node) => { + if (nodeEnclosesEvent(node, event)) { + found = node; + } + }); + if (found) { + insertRenderEvent(found, event); + } + }); +} +function nodeEnclosesEvent(node, event) { + return (node.data.min !== -1 && + node.data.max !== -1 && + node.data.min < event.ts && + event.ts + event.dur < node.data.max); +} +function insertRenderEvent(enclosingNode, event) { + const eventStart = event.ts; + const eventEnd = event.ts + event.dur; + const renderNode = enclosingNode.copy(); + renderNode.data = { + id: -1, + callFrame: { + functionName: event.name, + scriptId: -1, + url: '', + lineNumber: -1, + columnNumber: -1, + }, + children: [], + sampleCount: -1, + min: eventStart, + max: eventEnd, + total: 0, + self: 0, + }; + const children = getChildren(enclosingNode); + // Children who are fully to the left or right of the render event + const childrenForOriginal = children.filter(child => child.data.max < eventStart || child.data.min > eventEnd); + // Children who are fully within the render event + const childrenForRenderNode = children.filter(child => child.data.min > eventStart && child.data.max < eventEnd); + // Children who are split by the render event + const leftSplitChild = children.find(n => n.data.min < eventStart && n.data.max > eventStart); + const rightSplitChild = children.find(n => n.data.min < eventEnd && n.data.max > eventEnd); + // Fix parent/child links for all children other then split children + enclosingNode.children = childrenForOriginal; + renderNode.children = childrenForRenderNode; + childrenForRenderNode.forEach(child => (child.parent = renderNode)); + // fix node/render node parent/child link + renderNode.parent = enclosingNode; + insertChildInOrder(enclosingNode.children, renderNode); + splitChild(enclosingNode, renderNode, leftSplitChild, eventStart); + splitChild(renderNode, enclosingNode, rightSplitChild, eventEnd); +} +function insertChildInOrder(children, node) { + let index = binsearch(children, node, (a, b) => a.data.min - b.data.min); + if (index < 0) { + /* tslint:disable:no-bitwise */ + index = ~index; + } + else { + // insert just after if ts order matched + index++; + } + children.splice(index, 0, node); +} +function splitChild(leftParent, rightParent, node, splitTS) { + if (node === undefined) { + return { middleLeftTime: 0, middleRightTime: 0 }; + } + // Split node + const left = node; + const right = node.copy(); + right.data = cloneDeep(node.data); + right.children = []; + left.data.max = splitTS; + right.data.min = splitTS; + // Add back in the child/parent links for the split node + left.parent = leftParent; + right.parent = rightParent; + insertChildInOrder(getChildren(leftParent), left); + insertChildInOrder(getChildren(rightParent), right); + const children = getChildren(node); + // If no further decendents, you are done + if (children.length === 0) { + left.data.self = left.data.max - left.data.min; + right.data.self = right.data.max - right.data.min; + return { middleLeftTime: left.data.self, middleRightTime: right.data.self }; + } + // Reasign children correctly + const middleChild = children.find(n => n.data.min < splitTS && n.data.max > splitTS); + const leftChildren = children.filter(child => child.data.max < left.data.max); + const rightChildren = children.filter(child => child.data.min > right.data.min); + left.children = leftChildren; + right.children = rightChildren; + // Start to sum self time of children + let leftChildrenTime = leftChildren.reduce((a, b) => a + b.data.self, 0); + let righChildrentTime = rightChildren.reduce((a, b) => a + b.data.self, 0); + // Split middle child and asign the resulting left/right node self times + const { middleLeftTime, middleRightTime } = splitChild(left, right, middleChild, splitTS); + leftChildrenTime += middleLeftTime; + righChildrentTime += middleRightTime; + left.data.self = left.data.max - left.data.min - leftChildrenTime; + right.data.self = right.data.max - right.data.min - righChildrentTime; + // Return the resulting left/right split times, so parents can determine their own self times + return { + middleLeftTime: left.data.max - left.data.min, + middleRightTime: right.data.max - right.data.min, + }; +} +export function isRenderEnd(event) { + return (event.ph === TRACE_EVENT_PHASE_NESTABLE_ASYNC_END && isRender(event.name)); +} +export function isRenderStart(event) { + return (event.ph === TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN && isRender(event.name)); +} +function isRenderPhase(event) { + return event.ph === TRACE_EVENT_PHASE_COMPLETE && isRender(event.name); +} +export function isRenderNode(node) { + return isRender(node.data.callFrame.functionName); +} +function isRender(name) { + return (name.endsWith('(Rendering: initial)') || + name.endsWith('(Rendering: update)') || + name.endsWith('(Rendering: outlet)')); +} diff --git a/src/tracerbench/trace/thread.js b/src/tracerbench/trace/thread.js new file mode 100644 index 0000000000000..410d19d69443a --- /dev/null +++ b/src/tracerbench/trace/thread.js @@ -0,0 +1,12 @@ +import Bounds from './bounds'; +export default class Thread { + constructor(id) { + this.bounds = new Bounds(); + this.events = []; + this.id = id; + } + addEvent(event) { + this.bounds.addEvent(event); + this.events.push(event); + } +} diff --git a/src/tracerbench/trace/trace.js b/src/tracerbench/trace/trace.js new file mode 100644 index 0000000000000..b16217224ffc1 --- /dev/null +++ b/src/tracerbench/trace/trace.js @@ -0,0 +1,292 @@ +/* tslint:disable:variable-name */ +/* tslint:disable:no-console */ +/* tslint:disable:no-bitwise */ +import binsearch from 'array-binsearch'; +import Bounds from './bounds'; +import Process from './process'; +import CpuProfile from './cpu-profile'; +import { isRenderEnd, isRenderStart } from './render-events'; +import { PROCESS_NAME, TRACE_EVENT_PHASE_BEGIN, TRACE_EVENT_PHASE_COMPLETE, TRACE_EVENT_PHASE_END, TRACE_EVENT_PHASE_METADATA, TRACE_EVENT_PHASE_SAMPLE, TRACE_EVENT_PHASE_INSTANT, } from './trace_event'; +import traceEventComparator from './trace_event_comparator'; +export default class Trace { + constructor() { + this.processes = []; + this.bounds = new Bounds(); + this.events = []; + this.browserProcess = null; + this.gpuProcess = null; + this.rendererProcesses = []; + this.parents = new Map(); + this.stack = []; + this.profileMap = new Map(); + } + cpuProfile(min, max) { + const { _cpuProfile } = this; + if (_cpuProfile === undefined) { + console.trace('public cpuProfile'); + throw new Error('trace is missing CpuProfile'); + } + return new CpuProfile(_cpuProfile, this.events, min, max); + } + process(pid) { + let process = this.findProcess(pid); + if (process === undefined) { + process = new Process(pid); + this.processes.push(process); + } + return process; + } + thread(pid, tid) { + return this.process(pid).thread(tid); + } + addEvents(events) { + for (const event of events) { + this.addEvent(event); + } + } + cpuProfileBuildModel(event) { + if (event.ph === TRACE_EVENT_PHASE_INSTANT && + event.cat === 'disabled-by-default-devtools.timeline') { + if (event.name === 'CpuProfile') { + this._cpuProfile = event.args.data.cpuProfile; + } + else if (event.name === 'TracingStartedInPage') { + this.lastTracingStartedInPageEvent = event; + } + } + else if (event.ph === TRACE_EVENT_PHASE_SAMPLE) { + if (event.name === 'Profile') { + const profile = event; + this.profileMap.set(profile.id, { + pid: profile.pid, + tid: profile.tid, + cpuProfile: { + startTime: profile.args.data.startTime, + endTime: 0, + duration: 0, + nodes: [], + samples: [], + timeDeltas: [], + }, + }); + } + else if (event.name === 'ProfileChunk') { + const profileChunk = event; + const profileEntry = this.profileMap.get(profileChunk.id); + if (profileChunk.args.data.cpuProfile.nodes) { + profileChunk.args.data.cpuProfile.nodes.forEach((node) => { + profileEntry.cpuProfile.nodes.push(Object.assign(node, { + sampleCount: 0, + min: 0, + max: 0, + total: 0, + self: 0, + })); + }); + } + profileEntry.cpuProfile.samples.push(...profileChunk.args.data.cpuProfile.samples); + profileEntry.cpuProfile.timeDeltas.push(...profileChunk.args.data.timeDeltas); + } + } + // determine main process + if (this.lastTracingStartedInPageEvent) { + // if this was recorded with the Performance tab, this should be the main process + this.mainProcess = this.process(this.lastTracingStartedInPageEvent.pid); + } + else { + // fallback to Renderer process with most events + this.mainProcess = this.processes + .filter(p => p.name === PROCESS_NAME.RENDERER) + .reduce((a, b) => (b.events.length > a.events.length ? b : a)); + } + for (const profileEntry of this.profileMap.values()) { + if (profileEntry.pid === this.mainProcess.id && + profileEntry.tid === this.mainProcess.mainThread.id) { + this._cpuProfile = profileEntry.cpuProfile; + const { nodes } = profileEntry.cpuProfile; + const nodeMap = new Map(); + nodes.forEach(node => nodeMap.set(node.id, node)); + nodes.forEach(node => { + if (node.parent !== undefined) { + const parent = nodeMap.get(node.parent); + if (!parent) { + return; // TODO Brian added this + } + if (parent.children) { + parent.children.push(node.id); + } + else { + parent.children = [node.id]; + } + } + }); + break; + } + } + } + buildModel() { + const { events } = this; + if (this.stack.length > 0) { + this.stack.length = 0; + } + for (const event of events) { + this.associateParent(event); + const process = this.process(event.pid); + process.addEvent(event); + this.cpuProfileBuildModel(event); + } + } + getParent(event) { + this.parents.get(event); + } + associateParent(event) { + if (event.ph !== TRACE_EVENT_PHASE_COMPLETE) { + return; + } + const { stack, parents } = this; + const { ts, pid, tid } = event; + + if (stack.length > 0) { // TODO Brian added this + for (let i = stack.length - 1; i >= 0; i--) { + const parent = stack[i]; + if (ts < parent.ts + parent.dur) { + if (parent.pid === pid && parent.tid === tid) { + parents.set(event, parent); + break; + } + } + else { + stack.splice(i, 1); + } + } + } // TODO Brian added this + stack.push(event); + } + addEvent(event) { + if (event.ph === TRACE_EVENT_PHASE_END || isRenderEnd(event)) { + this.endEvent(event); + return; + } + const events = this.events; + let index = binsearch(events, event, traceEventComparator); + if (index < 0) { + index = ~index; + } + else { + // insert just after if ts order matched + index++; + } + events.splice(index, 0, event); + if (event.ph === TRACE_EVENT_PHASE_METADATA) { + this.addMetadata(event); + return; + } + if (event.ph === TRACE_EVENT_PHASE_BEGIN || isRenderStart(event)) { + this.stack.push(event); + } + this.bounds.addEvent(event); + } + findProcess(pid) { + for (const process of this.processes) { + if (process.id === pid) { + return process; + } + } + return; + } + endEvent(end) { + const { stack } = this; + for (let i = stack.length - 1; i >= 0; i--) { + const begin = stack[i]; + if (begin.name === end.name && + begin.cat === end.cat && + begin.tid === end.tid && + begin.pid === end.pid) { + stack.splice(i, 1); + return this.completeEvent(begin, end); + } + } + throw new Error('could not find matching B phase for E phase event'); + } + completeEvent(begin, end) { + let args = '__stripped__'; + if (typeof begin.args === 'object' && begin.args !== null) { + args = Object.assign({}, begin.args); + } + if (typeof end.args === 'object' && end.args !== null) { + args = Object.assign(args === undefined ? {} : args, end.args); + } + const complete = { + args, + cat: begin.cat, + dur: end.ts - begin.ts, + name: begin.name, + ph: TRACE_EVENT_PHASE_COMPLETE, + pid: begin.pid, + tdur: end.tts - begin.tts, + tid: begin.tid, + ts: begin.ts, + tts: begin.tts, + }; + const { events } = this; + const index = binsearch(events, begin, traceEventComparator); + events[index] = complete; + } + addMetadata(event) { + const { pid, tid } = event; + if (event.args === '__stripped__') { + return; + } + switch (event.name) { + case 'num_cpus': + this.numberOfProcessors = event.args.number; + break; + case 'process_name': + const processName = event.args.name; + const process = this.process(pid); + process.name = processName; + if (processName === 'GPU Process') { + this.gpuProcess = process; + } + else if (processName === 'Browser') { + this.browserProcess = process; + } + else if (processName === 'Renderer') { + this.rendererProcesses.push(process); + } + break; + case 'process_labels': + this.process(pid).labels = event.args.labels; + break; + case 'process_sort_index': + this.process(pid).sortIndex = event.args.sort_index; + break; + case 'trace_buffer_overflowed': + this.process(pid).traceBufferOverflowedAt = event.args.overflowed_at_ts; + break; + case 'thread_name': + const threadName = event.args.name; + const thread = this.thread(pid, tid); + thread.name = threadName; + if (threadName === 'CrRendererMain') { + this.process(pid).mainThread = thread; + } + else if (threadName === 'ScriptStreamerThread') { + this.process(pid).scriptStreamerThread = thread; + } + break; + case 'thread_sort_index': + this.thread(pid, tid).sortIndex = event.args.sort_index; + break; + case 'IsTimeTicksHighResolution': + this.process(pid).isTimeTicksHighResolution = event.args.value; + break; + case 'TraceConfig': + this.process(pid).traceConfig = event.args.value; + break; + default: + // console.warn("unrecognized metadata:", JSON.stringify(event, null, 2)); + break; + } + } +} diff --git a/src/tracerbench/trace/trace_event.js b/src/tracerbench/trace/trace_event.js new file mode 100644 index 0000000000000..8d9c0499d3c05 --- /dev/null +++ b/src/tracerbench/trace/trace_event.js @@ -0,0 +1,54 @@ +export const TRACE_EVENT_PHASE_BEGIN = 'B'; +export const TRACE_EVENT_PHASE_END = 'E'; +export const TRACE_EVENT_PHASE_COMPLETE = 'X'; +export const TRACE_EVENT_PHASE_INSTANT = 'I'; +export const TRACE_EVENT_PHASE_ASYNC_BEGIN = 'S'; +export const TRACE_EVENT_PHASE_ASYNC_STEP_INTO = 'T'; +export const TRACE_EVENT_PHASE_ASYNC_STEP_PAST = 'p'; +export const TRACE_EVENT_PHASE_ASYNC_END = 'F'; +export const TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN = 'b'; +export const TRACE_EVENT_PHASE_NESTABLE_ASYNC_END = 'e'; +export const TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT = 'n'; +export const TRACE_EVENT_PHASE_FLOW_BEGIN = 's'; +export const TRACE_EVENT_PHASE_FLOW_STEP = 't'; +export const TRACE_EVENT_PHASE_FLOW_END = 'f'; +export const TRACE_EVENT_PHASE_METADATA = 'M'; +export const TRACE_EVENT_PHASE_COUNTER = 'C'; +export const TRACE_EVENT_PHASE_SAMPLE = 'P'; +export const TRACE_EVENT_PHASE_CREATE_OBJECT = 'N'; +export const TRACE_EVENT_PHASE_SNAPSHOT_OBJECT = 'O'; +export const TRACE_EVENT_PHASE_DELETE_OBJECT = 'D'; +export const TRACE_EVENT_PHASE_MEMORY_DUMP = 'v'; +export const TRACE_EVENT_PHASE_MARK = 'R'; +export const TRACE_EVENT_PHASE_CLOCK_SYNC = 'c'; +export const TRACE_EVENT_PHASE_ENTER_CONTEXT = '('; +export const TRACE_EVENT_PHASE_LEAVE_CONTEXT = ')'; +export const TRACE_EVENT_PHASE_LINK_IDS = '='; +export const TRACE_EVENT_SCOPE_NAME_GLOBAL = 'g'; +export const TRACE_EVENT_SCOPE_NAME_PROCESS = 'p'; +export const TRACE_EVENT_SCOPE_NAME_THREAD = 't'; + +export const TRACE_EVENT_NAME = { + TRACING_STARTED_IN_PAGE: 'TracingStartedInPage', + PROFILE: 'Profile', + PROFILE_CHUNK: 'ProfileChunk', + CPU_PROFILE: 'CpuProfile', + V8_EXECUTE: 'V8.Execute', +}; + +export const PROCESS_NAME = { + BROWSER: 'Browser', + RENDERER: 'Renderer', + GPU: 'GPU Process', +}; + +export const TRACE_METADATA_NAME = { + PROCESS_NAME: 'process_name', + PROCESS_LABELS: 'process_labels', + PROCESS_SORT_INDEX: 'process_sort_index', + PROCESS_UPTIME_SECONDS: 'process_uptime_seconds', + THREAD_NAME: 'thread_name', + THREAD_SORT_INDEX: 'thread_sort_index', + NUM_CPUS: 'num_cpus', + TRACE_BUFFER_OVERFLOWED: 'trace_buffer_overflowed', +}; \ No newline at end of file diff --git a/src/tracerbench/trace/trace_event_comparator.js b/src/tracerbench/trace/trace_event_comparator.js new file mode 100644 index 0000000000000..ea33b80b9bf71 --- /dev/null +++ b/src/tracerbench/trace/trace_event_comparator.js @@ -0,0 +1,34 @@ +import { TRACE_EVENT_PHASE_METADATA } from "./trace_event"; +export default function traceEventComparator(a, b) { + let res = 0; + if (a.ts !== b.ts) { + res = a.ts - b.ts; + } + else if (a.ph === TRACE_EVENT_PHASE_METADATA) { + res = -1; + } + else if (b.ph === TRACE_EVENT_PHASE_METADATA) { + res = 1; + } + if (res === 0) { + res = a.pid - b.pid; + if (res === 0) { + res = a.tid - b.tid; + if (res === 0) { + res = strcmp(a.ph, b.ph); + if (res === 0) { + res = strcmp(a.cat, b.cat); + if (res === 0) { + res = strcmp(a.name, b.name); + // TODO compare id, right now we only complete B/E + // if we do async events, this should compare ids too + } + } + } + } + } + return res; +} +function strcmp(a, b) { + return a < b ? -1 : a > b ? 1 : 0; +} diff --git a/src/types.js b/src/types.js new file mode 100644 index 0000000000000..17fb1e9f53e42 --- /dev/null +++ b/src/types.js @@ -0,0 +1,59 @@ +// @flow + +export type Milliseconds = number; + +export type ReactPriority = 'unscheduled' | 'high' | 'normal' | 'low'; + +export type ReactEventType = + | 'schedule-render' + | 'schedule-state-update' + | 'suspend'; + +export type ReactMeasureType = + | 'commit' + | 'render-idle' + | 'render' + | 'layout-effects' + | 'passive-effects'; + +export type ReactEvent = {| + +type: ReactEventType, + +priority: ReactPriority, + +timestamp: Milliseconds, + +componentName?: string, + +componentStack?: string, + +isCascading?: boolean, +|}; + +export type BatchUID = number; + +export type ReactMeasure = {| + +type: ReactMeasureType, + +priority: ReactPriority, + +timestamp: Milliseconds, + +duration: Milliseconds, + +batchUID: BatchUID, + +depth: number, +|}; + +export type ReactProfilerDataPriority = {| + events: Array, + measures: Array, +|}; + +export type ReactProfilerData = {| + unscheduled: ReactProfilerDataPriority, + high: ReactProfilerDataPriority, + normal: ReactProfilerDataPriority, + low: ReactProfilerDataPriority, +|}; + +export type ReactHoverContextInfo = {| + event: ReactEvent | null, + measure: ReactMeasure | null, + priorityIndex: number, + reactProfilerData: ReactProfilerData, + zeroAt: Milliseconds, +|}; + +export type FlamechartData = any; diff --git a/src/useDebounce.js b/src/useDebounce.js new file mode 100644 index 0000000000000..cc706172e0646 --- /dev/null +++ b/src/useDebounce.js @@ -0,0 +1,28 @@ +// Below copied from https://usehooks.com/ +export default function useDebounce(value, delay) { + // State and setters for debounced value + const [debouncedValue, setDebouncedValue] = useState(value); + + // Show the value in DevTools + useDebugValue(debouncedValue); + + useEffect( + () => { + // Update debounced value after delay + const handler = setTimeout(() => { + setDebouncedValue(value); + }, delay); + + // Cancel the timeout if value changes (also on delay change or unmount) + // This is how we prevent debounced value from updating if value is changed ... + // .. within the delay period. Timeout gets cleared and restarted. + return () => { + clearTimeout(handler); + }; + }, + [value, delay] // Only re-call effect if value or delay changes + ); + + return debouncedValue; +} +// Above copied from https://usehooks.com/ diff --git a/src/useInteractiveEvents.js b/src/useInteractiveEvents.js new file mode 100644 index 0000000000000..cb52eec8e7043 --- /dev/null +++ b/src/useInteractiveEvents.js @@ -0,0 +1,127 @@ +import { useEffect, useRef, useState } from 'react'; +import { durationToWidth, timestampToPosition } from './usePanAndZoom'; +import { EVENT_SIZE } from './constants'; + +function doesEventIntersectPosition(position, state, event) { + const { duration, timestamp } = event; + + // Although it would be intuitive to search by time, + // that can result in a confusing user experience for events of 0ms duration- + // because we may choose to render these anyway. + // The best way to compare is to convert event times to pixel coordinates and compare them. + let startX = timestampToPosition(timestamp, state); + let stopX = startX + durationToWidth(duration, state); + + if (duration !== undefined) { + if (position >= startX && position <= stopX) { + return true; + } + } else { + startX -= EVENT_SIZE / 2; + stopX = startX + EVENT_SIZE; + + if (position >= startX && position <= stopX) { + return true; + } + } + + return false; +} + +export default function useInteractiveEvents({ + canvasHeight, + canvasRef, + canvasWidth, + eventQueue, + state, +}) { + const { + canvasMouseX, + canvasMouseY, + fixedColumnWidth, + fixedHeaderHeight, + zoomLevel, + } = state; + + let hoveredEvent = null; + + const [selectedEvent, setSelectedEvent] = useState(null); + + const lastResultRef = useRef({ + eventQueue, + hoveredEvent, + selectedEvent, + }); + + useEffect(() => { + lastResultRef.current = { + eventQueue, + hoveredEvent, + selectedEvent, + }; + }); + + useEffect(() => { + const onClick = () => { + const { hoveredEvent, selectedEvent } = lastResultRef.current; + setSelectedEvent(hoveredEvent === selectedEvent ? null : hoveredEvent); + }; + const canvas = canvasRef.current; + canvas.addEventListener('click', onClick); + return () => { + canvas.removeEventListener('click', onClick); + }; + }, [canvasRef]); + + if (eventQueue == null) { + return [null, selectedEvent]; + } + + // Ignore mouse events that happen outside of the canvas. + if ( + canvasMouseX >= fixedColumnWidth && + canvasMouseX < canvasWidth && + canvasMouseY >= fixedHeaderHeight && + canvasMouseY < canvasHeight + ) { + // Small mouse movements won't change the hovered event, + // So always start by checking the last hovered event to see if we can avoid doing more work. + const lastEvents = lastResultRef.current.eventQueue; + const lastHoveredEvent = lastResultRef.current.hoveredEvent; + + if (lastHoveredEvent !== null && lastEvents === eventQueue) { + if (doesEventIntersectPosition(canvasMouseX, state, lastHoveredEvent)) { + hoveredEvent = lastHoveredEvent; + return [hoveredEvent, selectedEvent]; + } + } + + // TODO I think we coulsed use a binary search if we just looked at start times only! + // + // Since event data is sorted, it would be nice to use a binary search for faster comparison. + // A simple binary search would not work here though, because of overlapping intervals. + // For example, imagine an event sequence A-E, with overlapping events B and C, as shown below. + // + // AAAA BBBBBBBBBBBB DDD EE + // CCC + // (X) + // + // Given the cursor position X, it should match event B- + // but if it happens to be compared to C first, it would next be compared to D, + // and would ultimately fail to match any results. + // + // Eventually we should create a data structure like an interval tree while pre-processing, + // so that we could more efficiently search it. + // For now though we'll just do a brute force search since this is just a prototype. :) + + for (let i = 0; i < eventQueue.length; i++) { + const event = eventQueue[i]; + if (doesEventIntersectPosition(canvasMouseX, state, event)) { + hoveredEvent = event; + return [hoveredEvent, selectedEvent]; + } + } + } + + return [hoveredEvent, selectedEvent]; +} diff --git a/src/usePanAndZoom.js b/src/usePanAndZoom.js new file mode 100644 index 0000000000000..f64f7015532a6 --- /dev/null +++ b/src/usePanAndZoom.js @@ -0,0 +1,296 @@ +import { useEffect, useReducer } from 'react'; +import { getCanvasMousePos } from './canvasUtils'; +import { + BAR_HORIZONTAL_SPACING, + MAX_ZOOM_LEVEL, + MIN_BAR_WIDTH, + MIN_ZOOM_LEVEL, + MOVE_WHEEL_DELTA_THRESHOLD, + ZOOM_WHEEL_DELTA_THRESHOLD, +} from './constants'; + +const initialState = { + canvasHeight: 0, + canvasWidth: 0, + canvasMouseX: 0, + canvasMouseY: 0, + fixedColumnWidth: 0, + fixedHeaderHeight: 0, + isDragging: false, + minZoomLevel: 1, + offsetX: 0, + offsetY: 0, + unscaledContentHeight: 0, + unscaledContentWidth: 0, + zoomLevel: 1, +}; + +// TODO Account for fixed label width +export function positionToTimestamp(position, state) { + return (position - state.fixedColumnWidth + state.offsetX) / state.zoomLevel; +} + +// TODO Account for fixed label width +export function timestampToPosition(timestamp, state) { + return timestamp * state.zoomLevel + state.fixedColumnWidth - state.offsetX; +} + +export function durationToWidth(duration, state) { + return Math.max( + duration * state.zoomLevel - BAR_HORIZONTAL_SPACING, + MIN_BAR_WIDTH + ); +} + +function getMaxOffsetX(state) { + return ( + state.unscaledContentWidth * state.zoomLevel - + state.canvasWidth + + state.fixedColumnWidth + ); +} + +function getMaxOffsetY(state) { + return ( + state.unscaledContentHeight - state.canvasHeight + state.fixedHeaderHeight + ); +} + +function reducer(state, action) { + const { payload, type } = action; + switch (type) { + case 'initialize': + return { + ...state, + canvasHeight: payload.canvasHeight, + canvasWidth: payload.canvasWidth, + fixedColumnWidth: payload.fixedColumnWidth, + fixedHeaderHeight: payload.fixedHeaderHeight, + minZoomLevel: payload.minZoomLevel, + unscaledContentHeight: payload.unscaledContentHeight, + unscaledContentWidth: payload.unscaledContentWidth, + zoomLevel: payload.zoomLevel, + offsetX: clamp(0, getMaxOffsetX(state), state.offsetX), + offsetY: clamp(0, getMaxOffsetY(state), state.offsetY), + }; + case 'mouse-down': + return { + ...state, + isDragging: true, + }; + case 'mouse-move': + const { canvasMouseX, canvasMouseY } = getCanvasMousePos( + payload.canvas, + payload.event + ); + + if (state.isDragging) { + return { + ...state, + canvasMouseX, + canvasMouseY, + offsetX: clamp( + 0, + getMaxOffsetX(state), + state.offsetX - payload.event.movementX + ), + offsetY: clamp( + 0, + getMaxOffsetY(state), + state.offsetY + payload.event.movementY + ), + }; + } else { + return { + ...state, + canvasMouseX, + canvasMouseY, + }; + } + case 'mouse-up': + return { + ...state, + isDragging: false, + }; + case 'wheel': + const { canvas, event } = payload; + const { deltaX, deltaY } = event; + const { + minZoomLevel, + offsetX, + offsetY, + unscaledContentHeight, + unscaledContentWidth, + zoomLevel, + } = state; + + const absDeltaX = Math.abs(deltaX); + const absDeltaY = Math.abs(deltaY); + + if (absDeltaX > absDeltaY) { + if (absDeltaX > MOVE_WHEEL_DELTA_THRESHOLD) { + return { + ...state, + offsetX: clamp(0, getMaxOffsetX(state), offsetX + deltaX), + }; + } + } else { + if (event.shiftKey || event.ctrlKey || event.metaKey) { + if (absDeltaY > ZOOM_WHEEL_DELTA_THRESHOLD) { + const { canvasMouseX } = getCanvasMousePos(canvas, event); + + const nextState = { + ...state, + zoomLevel: clamp( + minZoomLevel, + MAX_ZOOM_LEVEL, + zoomLevel * (1 + 0.005 * -deltaY) + ), + }; + + // Determine what point in time the mouse is currently centered over, + // and adjust the offset so that point stays centered after zooming. + const timestampAtCurrentZoomLevel = positionToTimestamp( + canvasMouseX, + state + ); + const positionAtNewZoom = timestampToPosition( + timestampAtCurrentZoomLevel, + nextState + ); + + nextState.offsetX = clamp( + 0, + getMaxOffsetX(nextState), + offsetX + positionAtNewZoom - canvasMouseX + ); + + if (nextState.zoomLevel !== zoomLevel) { + return nextState; + } + } + } else { + if (absDeltaY > MOVE_WHEEL_DELTA_THRESHOLD) { + return { + ...state, + offsetY: clamp(0, getMaxOffsetY(state), offsetY + deltaY), + }; + } + } + } + break; + default: + throw Error(`Unexpected type "${type}"`); + } + + return state; +} + +function clamp(min, max, value) { + if (Number.isNaN(min) || Number.isNaN(max) || Number.isNaN(value)) { + debugger; + } + return Math.max(min, Math.min(max, value)); +} + +// Inspired by https://github.com/jsdf/flamechart +export default function usePanAndZoom({ + canvasRef, + canvasHeight, + canvasWidth, + fixedColumnWidth, + fixedHeaderHeight, + unscaledContentWidth, + unscaledContentHeight, +}) { + const [state, dispatch] = useReducer(reducer, initialState); + + // TODO This effect should run any time width or unscaledContentWidth changes + useEffect(() => { + const width = canvasWidth; + + const initialZoomLevel = clamp( + MIN_ZOOM_LEVEL, + MAX_ZOOM_LEVEL, + (width - fixedColumnWidth) / unscaledContentWidth + ); + + dispatch({ + type: 'initialize', + payload: { + canvasHeight, + canvasWidth, + fixedColumnWidth, + fixedHeaderHeight, + minZoomLevel: initialZoomLevel, + unscaledContentHeight, + unscaledContentWidth, + zoomLevel: initialZoomLevel, + }, + }); + }, [ + canvasHeight, + canvasWidth, + fixedHeaderHeight, + fixedColumnWidth, + unscaledContentHeight, + unscaledContentWidth, + ]); + + useEffect(() => { + const canvas = canvasRef.current; + + const onCanvasMouseDown = event => { + dispatch({ type: 'mouse-down' }); + }; + + const onCanvasMouseMove = event => { + dispatch({ + type: 'mouse-move', + payload: { + canvas: canvasRef.current, + event, + }, + }); + }; + + const onDocumentMouseUp = event => { + dispatch({ type: 'mouse-up' }); + }; + + const onCanvasWheel = event => { + event.preventDefault(); + event.stopPropagation(); + + dispatch({ + type: 'wheel', + payload: { + canvas, + event, + }, + }); + + return false; + }; + + document.addEventListener('mouseup', onDocumentMouseUp); + + if (canvas instanceof HTMLCanvasElement) { + canvas.addEventListener('wheel', onCanvasWheel); + canvas.addEventListener('mousedown', onCanvasMouseDown); + canvas.addEventListener('mousemove', onCanvasMouseMove); + } + + return () => { + document.removeEventListener('mouseup', onDocumentMouseUp); + + if (canvas instanceof HTMLCanvasElement) { + canvas.removeEventListener('wheel', onCanvasWheel); + canvas.removeEventListener('mousedown', onCanvasMouseDown); + canvas.removeEventListener('mousemove', onCanvasMouseMove); + } + }; + }, [canvasRef]); + + return state; +} diff --git a/src/useSmartTooltip.js b/src/useSmartTooltip.js new file mode 100644 index 0000000000000..c7a1484f60e71 --- /dev/null +++ b/src/useSmartTooltip.js @@ -0,0 +1,57 @@ +// @flow + +import { useLayoutEffect, useRef } from 'react'; + +const TOOLTIP_OFFSET = 4; + +export default function useSmartTooltip({ mouseX, mouseY }) { + const ref = useRef(null); + + useLayoutEffect(() => { + const element = ref.current; + if (element !== null) { + // Let's check the vertical position. + if ( + mouseY + TOOLTIP_OFFSET + element.offsetHeight >= + window.innerHeight + ) { + // The tooltip doesn't fit below the mouse cursor (which is our + // default strategy). Therefore we try to position it either above the + // mouse cursor or finally aligned with the window's top edge. + if (mouseY - TOOLTIP_OFFSET - element.offsetHeight > 0) { + // We position the tooltip above the mouse cursor if it fits there. + element.style.top = `${mouseY - + element.offsetHeight - + TOOLTIP_OFFSET}px`; + } else { + // Otherwise we align the tooltip with the window's top edge. + element.style.top = '0px'; + } + } else { + element.style.top = `${mouseY + TOOLTIP_OFFSET}px`; + } + + // Now let's check the horizontal position. + if (mouseX + TOOLTIP_OFFSET + element.offsetWidth >= window.innerWidth) { + // The tooltip doesn't fit at the right of the mouse cursor (which is + // our default strategy). Therefore we try to position it either at the + // left of the mouse cursor or finally aligned with the window's left + // edge. + if (mouseX - TOOLTIP_OFFSET - element.offsetWidth > 0) { + // We position the tooltip at the left of the mouse cursor if it fits + // there. + element.style.left = `${mouseX - + element.offsetWidth - + TOOLTIP_OFFSET}px`; + } else { + // Otherwise, align the tooltip with the window's left edge. + element.style.left = '0px'; + } + } else { + element.style.left = `${mouseX + TOOLTIP_OFFSET}px`; + } + } + }); + + return ref; +} diff --git a/src/utils.js b/src/utils.js new file mode 100644 index 0000000000000..f2ec6906cdfd1 --- /dev/null +++ b/src/utils.js @@ -0,0 +1,46 @@ +// @flow + +import memoize from 'memoize-one'; + +import type { + BatchUID, + Milliseconds, + ReactPriority, + ReactProfilerData, +} from '../types'; + +// TODO Batch duration probably shouldn't include delayed passive effects? +// It should probably end with the layout effect. + +function unmemoizedGetBatchRange( + batchUID: BatchUID, + priority: ReactPriority, + data: ReactProfilerData +): [Milliseconds, Milliseconds] { + const { measures } = data[priority]; + + let startTime = 0; + let stopTime = Infinity; + + let i = 0; + + for (i; i < measures.length; i++) { + const measure = measures[i]; + if (measure.batchUID === batchUID) { + startTime = measure.timestamp; + break; + } + } + + for (i; i < measures.length; i++) { + const measure = measures[i]; + stopTime = measure.timestamp; + if (measure.batchUID !== batchUID) { + break; + } + } + + return [startTime, stopTime]; +} + +export const getBatchRange = memoize(unmemoizedGetBatchRange); diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000000000..04a77f2852374 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,6331 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.5.5": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d" + integrity sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw== + dependencies: + "@babel/highlight" "^7.0.0" + +"@babel/core@^7.0.0": + version "7.7.2" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.7.2.tgz#ea5b99693bcfc058116f42fa1dd54da412b29d91" + integrity sha512-eeD7VEZKfhK1KUXGiyPFettgF3m513f8FoBSWiQ1xTvl1RAopLs42Wp9+Ze911I6H0N9lNqJMDgoZT7gHsipeQ== + dependencies: + "@babel/code-frame" "^7.5.5" + "@babel/generator" "^7.7.2" + "@babel/helpers" "^7.7.0" + "@babel/parser" "^7.7.2" + "@babel/template" "^7.7.0" + "@babel/traverse" "^7.7.2" + "@babel/types" "^7.7.2" + convert-source-map "^1.7.0" + debug "^4.1.0" + json5 "^2.1.0" + lodash "^4.17.13" + resolve "^1.3.2" + semver "^5.4.1" + source-map "^0.5.0" + +"@babel/generator@^7.0.0", "@babel/generator@^7.3.3", "@babel/generator@^7.7.2": + version "7.7.2" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.7.2.tgz#2f4852d04131a5e17ea4f6645488b5da66ebf3af" + integrity sha512-WthSArvAjYLz4TcbKOi88me+KmDJdKSlfwwN8CnUYn9jBkzhq0ZEPuBfkAWIvjJ3AdEV1Cf/+eSQTnp3IDJKlQ== + dependencies: + "@babel/types" "^7.7.2" + jsesc "^2.5.1" + lodash "^4.17.13" + source-map "^0.5.0" + +"@babel/helper-annotate-as-pure@^7.0.0", "@babel/helper-annotate-as-pure@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.7.0.tgz#efc54032d43891fe267679e63f6860aa7dbf4a5e" + integrity sha512-k50CQxMlYTYo+GGyUGFwpxKVtxVJi9yh61sXZji3zYHccK9RYliZGSTOgci85T+r+0VFN2nWbGM04PIqwfrpMg== + dependencies: + "@babel/types" "^7.7.0" + +"@babel/helper-builder-binary-assignment-operator-visitor@^7.1.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.7.0.tgz#32dd9551d6ed3a5fc2edc50d6912852aa18274d9" + integrity sha512-Cd8r8zs4RKDwMG/92lpZcnn5WPQ3LAMQbCw42oqUh4s7vsSN5ANUZjMel0OOnxDLq57hoDDbai+ryygYfCTOsw== + dependencies: + "@babel/helper-explode-assignable-expression" "^7.7.0" + "@babel/types" "^7.7.0" + +"@babel/helper-builder-react-jsx@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.7.0.tgz#c6b8254d305bacd62beb648e4dea7d3ed79f352d" + integrity sha512-LSln3cexwInTMYYoFeVLKnYPPMfWNJ8PubTBs3hkh7wCu9iBaqq1OOyW+xGmEdLxT1nhsl+9SJ+h2oUDYz0l2A== + dependencies: + "@babel/types" "^7.7.0" + esutils "^2.0.0" + +"@babel/helper-call-delegate@^7.4.4": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/helper-call-delegate/-/helper-call-delegate-7.7.0.tgz#df8942452c2c1a217335ca7e393b9afc67f668dc" + integrity sha512-Su0Mdq7uSSWGZayGMMQ+z6lnL00mMCnGAbO/R0ZO9odIdB/WNU/VfQKqMQU0fdIsxQYbRjDM4BixIa93SQIpvw== + dependencies: + "@babel/helper-hoist-variables" "^7.7.0" + "@babel/traverse" "^7.7.0" + "@babel/types" "^7.7.0" + +"@babel/helper-create-class-features-plugin@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.7.0.tgz#bcdc223abbfdd386f94196ae2544987f8df775e8" + integrity sha512-MZiB5qvTWoyiFOgootmRSDV1udjIqJW/8lmxgzKq6oDqxdmHUjeP2ZUOmgHdYjmUVNABqRrHjYAYRvj8Eox/UA== + dependencies: + "@babel/helper-function-name" "^7.7.0" + "@babel/helper-member-expression-to-functions" "^7.7.0" + "@babel/helper-optimise-call-expression" "^7.7.0" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-replace-supers" "^7.7.0" + "@babel/helper-split-export-declaration" "^7.7.0" + +"@babel/helper-create-regexp-features-plugin@^7.7.0": + version "7.7.2" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.7.2.tgz#6f20443778c8fce2af2ff4206284afc0ced65db6" + integrity sha512-pAil/ZixjTlrzNpjx+l/C/wJk002Wo7XbbZ8oujH/AoJ3Juv0iN/UTcPUHXKMFLqsfS0Hy6Aow8M31brUYBlQQ== + dependencies: + "@babel/helper-regex" "^7.4.4" + regexpu-core "^4.6.0" + +"@babel/helper-define-map@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.7.0.tgz#60b0e9fd60def9de5054c38afde8c8ee409c7529" + integrity sha512-kPKWPb0dMpZi+ov1hJiwse9dWweZsz3V9rP4KdytnX1E7z3cTNmFGglwklzFPuqIcHLIY3bgKSs4vkwXXdflQA== + dependencies: + "@babel/helper-function-name" "^7.7.0" + "@babel/types" "^7.7.0" + lodash "^4.17.13" + +"@babel/helper-explode-assignable-expression@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.7.0.tgz#db2a6705555ae1f9f33b4b8212a546bc7f9dc3ef" + integrity sha512-CDs26w2shdD1urNUAji2RJXyBFCaR+iBEGnFz3l7maizMkQe3saVw9WtjG1tz8CwbjvlFnaSLVhgnu1SWaherg== + dependencies: + "@babel/traverse" "^7.7.0" + "@babel/types" "^7.7.0" + +"@babel/helper-function-name@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.7.0.tgz#44a5ad151cfff8ed2599c91682dda2ec2c8430a3" + integrity sha512-tDsJgMUAP00Ugv8O2aGEua5I2apkaQO7lBGUq1ocwN3G23JE5Dcq0uh3GvFTChPa4b40AWiAsLvCZOA2rdnQ7Q== + dependencies: + "@babel/helper-get-function-arity" "^7.7.0" + "@babel/template" "^7.7.0" + "@babel/types" "^7.7.0" + +"@babel/helper-get-function-arity@^7.0.0", "@babel/helper-get-function-arity@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.0.tgz#c604886bc97287a1d1398092bc666bc3d7d7aa2d" + integrity sha512-tLdojOTz4vWcEnHWHCuPN5P85JLZWbm5Fx5ZsMEMPhF3Uoe3O7awrbM2nQ04bDOUToH/2tH/ezKEOR8zEYzqyw== + dependencies: + "@babel/types" "^7.7.0" + +"@babel/helper-hoist-variables@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.7.0.tgz#b4552e4cfe5577d7de7b183e193e84e4ec538c81" + integrity sha512-LUe/92NqsDAkJjjCEWkNe+/PcpnisvnqdlRe19FahVapa4jndeuJ+FBiTX1rcAKWKcJGE+C3Q3tuEuxkSmCEiQ== + dependencies: + "@babel/types" "^7.7.0" + +"@babel/helper-member-expression-to-functions@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.7.0.tgz#472b93003a57071f95a541ea6c2b098398bcad8a" + integrity sha512-QaCZLO2RtBcmvO/ekOLp8p7R5X2JriKRizeDpm5ChATAFWrrYDcDxPuCIBXKyBjY+i1vYSdcUTMIb8psfxHDPA== + dependencies: + "@babel/types" "^7.7.0" + +"@babel/helper-module-imports@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.7.0.tgz#99c095889466e5f7b6d66d98dffc58baaf42654d" + integrity sha512-Dv3hLKIC1jyfTkClvyEkYP2OlkzNvWs5+Q8WgPbxM5LMeorons7iPP91JM+DU7tRbhqA1ZeooPaMFvQrn23RHw== + dependencies: + "@babel/types" "^7.7.0" + +"@babel/helper-module-transforms@^7.1.0", "@babel/helper-module-transforms@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.7.0.tgz#154a69f0c5b8fd4d39e49750ff7ac4faa3f36786" + integrity sha512-rXEefBuheUYQyX4WjV19tuknrJFwyKw0HgzRwbkyTbB+Dshlq7eqkWbyjzToLrMZk/5wKVKdWFluiAsVkHXvuQ== + dependencies: + "@babel/helper-module-imports" "^7.7.0" + "@babel/helper-simple-access" "^7.7.0" + "@babel/helper-split-export-declaration" "^7.7.0" + "@babel/template" "^7.7.0" + "@babel/types" "^7.7.0" + lodash "^4.17.13" + +"@babel/helper-optimise-call-expression@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.7.0.tgz#4f66a216116a66164135dc618c5d8b7a959f9365" + integrity sha512-48TeqmbazjNU/65niiiJIJRc5JozB8acui1OS7bSd6PgxfuovWsvjfWSzlgx+gPFdVveNzUdpdIg5l56Pl5jqg== + dependencies: + "@babel/types" "^7.7.0" + +"@babel/helper-plugin-utils@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz#bbb3fbee98661c569034237cc03967ba99b4f250" + integrity sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA== + +"@babel/helper-regex@^7.0.0", "@babel/helper-regex@^7.4.4": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.5.5.tgz#0aa6824f7100a2e0e89c1527c23936c152cab351" + integrity sha512-CkCYQLkfkiugbRDO8eZn6lRuR8kzZoGXCg3149iTk5se7g6qykSpy3+hELSwquhu+TgHn8nkLiBwHvNX8Hofcw== + dependencies: + lodash "^4.17.13" + +"@babel/helper-remap-async-to-generator@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.7.0.tgz#4d69ec653e8bff5bce62f5d33fc1508f223c75a7" + integrity sha512-pHx7RN8X0UNHPB/fnuDnRXVZ316ZigkO8y8D835JlZ2SSdFKb6yH9MIYRU4fy/KPe5sPHDFOPvf8QLdbAGGiyw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.7.0" + "@babel/helper-wrap-function" "^7.7.0" + "@babel/template" "^7.7.0" + "@babel/traverse" "^7.7.0" + "@babel/types" "^7.7.0" + +"@babel/helper-replace-supers@^7.5.5", "@babel/helper-replace-supers@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.7.0.tgz#d5365c8667fe7cbd13b8ddddceb9bd7f2b387512" + integrity sha512-5ALYEul5V8xNdxEeWvRsBzLMxQksT7MaStpxjJf9KsnLxpAKBtfw5NeMKZJSYDa0lKdOcy0g+JT/f5mPSulUgg== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.7.0" + "@babel/helper-optimise-call-expression" "^7.7.0" + "@babel/traverse" "^7.7.0" + "@babel/types" "^7.7.0" + +"@babel/helper-simple-access@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.7.0.tgz#97a8b6c52105d76031b86237dc1852b44837243d" + integrity sha512-AJ7IZD7Eem3zZRuj5JtzFAptBw7pMlS3y8Qv09vaBWoFsle0d1kAn5Wq6Q9MyBXITPOKnxwkZKoAm4bopmv26g== + dependencies: + "@babel/template" "^7.7.0" + "@babel/types" "^7.7.0" + +"@babel/helper-split-export-declaration@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.0.tgz#1365e74ea6c614deeb56ebffabd71006a0eb2300" + integrity sha512-HgYSI8rH08neWlAH3CcdkFg9qX9YsZysZI5GD8LjhQib/mM0jGOZOVkoUiiV2Hu978fRtjtsGsW6w0pKHUWtqA== + dependencies: + "@babel/types" "^7.7.0" + +"@babel/helper-wrap-function@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.7.0.tgz#15af3d3e98f8417a60554acbb6c14e75e0b33b74" + integrity sha512-sd4QjeMgQqzshSjecZjOp8uKfUtnpmCyQhKQrVJBBgeHAB/0FPi33h3AbVlVp07qQtMD4QgYSzaMI7VwncNK/w== + dependencies: + "@babel/helper-function-name" "^7.7.0" + "@babel/template" "^7.7.0" + "@babel/traverse" "^7.7.0" + "@babel/types" "^7.7.0" + +"@babel/helpers@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.7.0.tgz#359bb5ac3b4726f7c1fde0ec75f64b3f4275d60b" + integrity sha512-VnNwL4YOhbejHb7x/b5F39Zdg5vIQpUUNzJwx0ww1EcVRt41bbGRZWhAURrfY32T5zTT3qwNOQFWpn+P0i0a2g== + dependencies: + "@babel/template" "^7.7.0" + "@babel/traverse" "^7.7.0" + "@babel/types" "^7.7.0" + +"@babel/highlight@^7.0.0": + version "7.5.0" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.5.0.tgz#56d11312bd9248fa619591d02472be6e8cb32540" + integrity sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ== + dependencies: + chalk "^2.0.0" + esutils "^2.0.2" + js-tokens "^4.0.0" + +"@babel/parser@^7.0.0", "@babel/parser@^7.7.0", "@babel/parser@^7.7.2": + version "7.7.3" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.3.tgz#5fad457c2529de476a248f75b0f090b3060af043" + integrity sha512-bqv+iCo9i+uLVbI0ILzKkvMorqxouI+GbV13ivcARXn9NNEabi2IEz912IgNpT/60BNXac5dgcfjb94NjsF33A== + +"@babel/plugin-proposal-async-generator-functions@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.7.0.tgz#83ef2d6044496b4c15d8b4904e2219e6dccc6971" + integrity sha512-ot/EZVvf3mXtZq0Pd0+tSOfGWMizqmOohXmNZg6LNFjHOV+wOPv7BvVYh8oPR8LhpIP3ye8nNooKL50YRWxpYA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-remap-async-to-generator" "^7.7.0" + "@babel/plugin-syntax-async-generators" "^7.2.0" + +"@babel/plugin-proposal-dynamic-import@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.7.0.tgz#dc02a8bad8d653fb59daf085516fa416edd2aa7f" + integrity sha512-7poL3Xi+QFPC7sGAzEIbXUyYzGJwbc2+gSD0AkiC5k52kH2cqHdqxm5hNFfLW3cRSTcx9bN0Fl7/6zWcLLnKAQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-dynamic-import" "^7.2.0" + +"@babel/plugin-proposal-json-strings@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz#568ecc446c6148ae6b267f02551130891e29f317" + integrity sha512-MAFV1CA/YVmYwZG0fBQyXhmj0BHCB5egZHCKWIFVv/XCxAeVGIHfos3SwDck4LvCllENIAg7xMKOG5kH0dzyUg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-json-strings" "^7.2.0" + +"@babel/plugin-proposal-object-rest-spread@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.6.2.tgz#8ffccc8f3a6545e9f78988b6bf4fe881b88e8096" + integrity sha512-LDBXlmADCsMZV1Y9OQwMc0MyGZ8Ta/zlD9N67BfQT8uYwkRswiu2hU6nJKrjrt/58aH/vqfQlR/9yId/7A2gWw== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-object-rest-spread" "^7.2.0" + +"@babel/plugin-proposal-optional-catch-binding@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz#135d81edb68a081e55e56ec48541ece8065c38f5" + integrity sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-optional-catch-binding" "^7.2.0" + +"@babel/plugin-proposal-unicode-property-regex@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.7.0.tgz#549fe1717a1bd0a2a7e63163841cb37e78179d5d" + integrity sha512-mk34H+hp7kRBWJOOAR0ZMGCydgKMD4iN9TpDRp3IIcbunltxEY89XSimc6WbtSLCDrwcdy/EEw7h5CFCzxTchw== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.7.0" + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-syntax-async-generators@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz#69e1f0db34c6f5a0cf7e2b3323bf159a76c8cb7f" + integrity sha512-1ZrIRBv2t0GSlcwVoQ6VgSLpLgiN/FVQUzt9znxo7v2Ov4jJrs8RY8tv0wvDmFN3qIdMKWrmMMW6yZ0G19MfGg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-syntax-dynamic-import@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.2.0.tgz#69c159ffaf4998122161ad8ebc5e6d1f55df8612" + integrity sha512-mVxuJ0YroI/h/tbFTPGZR8cv6ai+STMKNBq0f8hFxsxWjl94qqhsb+wXbpNMDPU3cfR1TIsVFzU3nXyZMqyK4w== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-syntax-flow@^7.2.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.7.0.tgz#5c9465bcd26354d5215294ea90ab1c706a571386" + integrity sha512-vQMV07p+L+jZeUnvX3pEJ9EiXGCjB5CTTvsirFD9rpEuATnoAvLBLoYbw1v5tyn3d2XxSuvEKi8cV3KqYUa0vQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-syntax-json-strings@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz#72bd13f6ffe1d25938129d2a186b11fd62951470" + integrity sha512-5UGYnMSLRE1dqqZwug+1LISpA403HzlSfsg6P9VXU6TBjcSHeNlw4DxDx7LgpF+iKZoOG/+uzqoRHTdcUpiZNg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-syntax-jsx@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.2.0.tgz#0b85a3b4bc7cdf4cc4b8bf236335b907ca22e7c7" + integrity sha512-VyN4QANJkRW6lDBmENzRszvZf3/4AXaj9YR7GwrWeeN9tEBPuXbmDYVU9bYBN0D70zCWVwUy0HWq2553VCb6Hw== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-syntax-object-rest-spread@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz#3b7a3e733510c57e820b9142a6579ac8b0dfad2e" + integrity sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-syntax-optional-catch-binding@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz#a94013d6eda8908dfe6a477e7f9eda85656ecf5c" + integrity sha512-bDe4xKNhb0LI7IvZHiA13kff0KEfaGX/Hv4lMA9+7TEc63hMNvfKo6ZFpXhKuEp+II/q35Gc4NoMeDZyaUbj9w== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-syntax-top-level-await@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.7.0.tgz#f5699549f50bbe8d12b1843a4e82f0a37bb65f4d" + integrity sha512-hi8FUNiFIY1fnUI2n1ViB1DR0R4QeK4iHcTlW6aJkrPoTdb8Rf1EMQ6GT3f67DDkYyWgew9DFoOZ6gOoEsdzTA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-syntax-typescript@^7.2.0": + version "7.3.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.3.3.tgz#a7cc3f66119a9f7ebe2de5383cce193473d65991" + integrity sha512-dGwbSMA1YhVS8+31CnPR7LB4pcbrzcV99wQzby4uAfrkZPYZlQ7ImwdpzLqi6Z6IL02b8IAL379CaMwo0x5Lag== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-arrow-functions@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz#9aeafbe4d6ffc6563bf8f8372091628f00779550" + integrity sha512-ER77Cax1+8/8jCB9fo4Ud161OZzWN5qawi4GusDuRLcDbDG+bIGYY20zb2dfAFdTRGzrfq2xZPvF0R64EHnimg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-async-to-generator@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.7.0.tgz#e2b84f11952cf5913fe3438b7d2585042772f492" + integrity sha512-vLI2EFLVvRBL3d8roAMqtVY0Bm9C1QzLkdS57hiKrjUBSqsQYrBsMCeOg/0KK7B0eK9V71J5mWcha9yyoI2tZw== + dependencies: + "@babel/helper-module-imports" "^7.7.0" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-remap-async-to-generator" "^7.7.0" + +"@babel/plugin-transform-block-scoped-functions@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz#5d3cc11e8d5ddd752aa64c9148d0db6cb79fd190" + integrity sha512-ntQPR6q1/NKuphly49+QiQiTN0O63uOwjdD6dhIjSWBI5xlrbUFh720TIpzBhpnrLfv2tNH/BXvLIab1+BAI0w== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-block-scoping@^7.6.3": + version "7.6.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.6.3.tgz#6e854e51fbbaa84351b15d4ddafe342f3a5d542a" + integrity sha512-7hvrg75dubcO3ZI2rjYTzUrEuh1E9IyDEhhB6qfcooxhDA33xx2MasuLVgdxzcP6R/lipAC6n9ub9maNW6RKdw== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + lodash "^4.17.13" + +"@babel/plugin-transform-classes@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.7.0.tgz#b411ecc1b8822d24b81e5d184f24149136eddd4a" + integrity sha512-/b3cKIZwGeUesZheU9jNYcwrEA7f/Bo4IdPmvp7oHgvks2majB5BoT5byAql44fiNQYOPzhk2w8DbgfuafkMoA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.7.0" + "@babel/helper-define-map" "^7.7.0" + "@babel/helper-function-name" "^7.7.0" + "@babel/helper-optimise-call-expression" "^7.7.0" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-replace-supers" "^7.7.0" + "@babel/helper-split-export-declaration" "^7.7.0" + globals "^11.1.0" + +"@babel/plugin-transform-computed-properties@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz#83a7df6a658865b1c8f641d510c6f3af220216da" + integrity sha512-kP/drqTxY6Xt3NNpKiMomfgkNn4o7+vKxK2DDKcBG9sHj51vHqMBGy8wbDS/J4lMxnqs153/T3+DmCEAkC5cpA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-destructuring@^7.6.0": + version "7.6.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.6.0.tgz#44bbe08b57f4480094d57d9ffbcd96d309075ba6" + integrity sha512-2bGIS5P1v4+sWTCnKNDZDxbGvEqi0ijeqM/YqHtVGrvG2y0ySgnEEhXErvE9dA0bnIzY9bIzdFK0jFA46ASIIQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-dotall-regex@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.7.0.tgz#c5c9ecacab3a5e0c11db6981610f0c32fd698b3b" + integrity sha512-3QQlF7hSBnSuM1hQ0pS3pmAbWLax/uGNCbPBND9y+oJ4Y776jsyujG2k0Sn2Aj2a0QwVOiOFL5QVPA7spjvzSA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.7.0" + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-duplicate-keys@^7.5.0": + version "7.5.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.5.0.tgz#c5dbf5106bf84cdf691222c0974c12b1df931853" + integrity sha512-igcziksHizyQPlX9gfSjHkE2wmoCH3evvD2qR5w29/Dk0SMKE/eOI7f1HhBdNhR/zxJDqrgpoDTq5YSLH/XMsQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-exponentiation-operator@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz#a63868289e5b4007f7054d46491af51435766008" + integrity sha512-umh4hR6N7mu4Elq9GG8TOu9M0bakvlsREEC+ialrQN6ABS4oDQ69qJv1VtR3uxlKMCQMCvzk7vr17RHKcjx68A== + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.1.0" + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-flow-strip-types@^7.0.0": + version "7.6.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.6.3.tgz#8110f153e7360cfd5996eee68706cfad92d85256" + integrity sha512-l0ETkyEofkqFJ9LS6HChNIKtVJw2ylKbhYMlJ5C6df+ldxxaLIyXY4yOdDQQspfFpV8/vDiaWoJlvflstlYNxg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-flow" "^7.2.0" + +"@babel/plugin-transform-for-of@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.4.tgz#0267fc735e24c808ba173866c6c4d1440fc3c556" + integrity sha512-9T/5Dlr14Z9TIEXLXkt8T1DU7F24cbhwhMNUziN3hB1AXoZcdzPcTiKGRn/6iOymDqtTKWnr/BtRKN9JwbKtdQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-function-name@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.7.0.tgz#0fa786f1eef52e3b7d4fc02e54b2129de8a04c2a" + integrity sha512-P5HKu0d9+CzZxP5jcrWdpe7ZlFDe24bmqP6a6X8BHEBl/eizAsY8K6LX8LASZL0Jxdjm5eEfzp+FIrxCm/p8bA== + dependencies: + "@babel/helper-function-name" "^7.7.0" + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-literals@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz#690353e81f9267dad4fd8cfd77eafa86aba53ea1" + integrity sha512-2ThDhm4lI4oV7fVQ6pNNK+sx+c/GM5/SaML0w/r4ZB7sAneD/piDJtwdKlNckXeyGK7wlwg2E2w33C/Hh+VFCg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-member-expression-literals@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.2.0.tgz#fa10aa5c58a2cb6afcf2c9ffa8cb4d8b3d489a2d" + integrity sha512-HiU3zKkSU6scTidmnFJ0bMX8hz5ixC93b4MHMiYebmk2lUVNGOboPsqQvx5LzooihijUoLR/v7Nc1rbBtnc7FA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-modules-amd@^7.5.0": + version "7.5.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.5.0.tgz#ef00435d46da0a5961aa728a1d2ecff063e4fb91" + integrity sha512-n20UsQMKnWrltocZZm24cRURxQnWIvsABPJlw/fvoy9c6AgHZzoelAIzajDHAQrDpuKFFPPcFGd7ChsYuIUMpg== + dependencies: + "@babel/helper-module-transforms" "^7.1.0" + "@babel/helper-plugin-utils" "^7.0.0" + babel-plugin-dynamic-import-node "^2.3.0" + +"@babel/plugin-transform-modules-commonjs@^7.0.0", "@babel/plugin-transform-modules-commonjs@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.7.0.tgz#3e5ffb4fd8c947feede69cbe24c9554ab4113fe3" + integrity sha512-KEMyWNNWnjOom8vR/1+d+Ocz/mILZG/eyHHO06OuBQ2aNhxT62fr4y6fGOplRx+CxCSp3IFwesL8WdINfY/3kg== + dependencies: + "@babel/helper-module-transforms" "^7.7.0" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-simple-access" "^7.7.0" + babel-plugin-dynamic-import-node "^2.3.0" + +"@babel/plugin-transform-modules-systemjs@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.7.0.tgz#9baf471213af9761c1617bb12fd278e629041417" + integrity sha512-ZAuFgYjJzDNv77AjXRqzQGlQl4HdUM6j296ee4fwKVZfhDR9LAGxfvXjBkb06gNETPnN0sLqRm9Gxg4wZH6dXg== + dependencies: + "@babel/helper-hoist-variables" "^7.7.0" + "@babel/helper-plugin-utils" "^7.0.0" + babel-plugin-dynamic-import-node "^2.3.0" + +"@babel/plugin-transform-modules-umd@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.7.0.tgz#d62c7da16670908e1d8c68ca0b5d4c0097b69966" + integrity sha512-u7eBA03zmUswQ9LQ7Qw0/ieC1pcAkbp5OQatbWUzY1PaBccvuJXUkYzoN1g7cqp7dbTu6Dp9bXyalBvD04AANA== + dependencies: + "@babel/helper-module-transforms" "^7.7.0" + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-named-capturing-groups-regex@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.7.0.tgz#358e6fd869b9a4d8f5cbc79e4ed4fc340e60dcaf" + integrity sha512-+SicSJoKouPctL+j1pqktRVCgy+xAch1hWWTMy13j0IflnyNjaoskj+DwRQFimHbLqO3sq2oN2CXMvXq3Bgapg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.7.0" + +"@babel/plugin-transform-new-target@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.4.4.tgz#18d120438b0cc9ee95a47f2c72bc9768fbed60a5" + integrity sha512-r1z3T2DNGQwwe2vPGZMBNjioT2scgWzK9BCnDEh+46z8EEwXBq24uRzd65I7pjtugzPSj921aM15RpESgzsSuA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-object-super@^7.5.5": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.5.5.tgz#c70021df834073c65eb613b8679cc4a381d1a9f9" + integrity sha512-un1zJQAhSosGFBduPgN/YFNvWVpRuHKU7IHBglLoLZsGmruJPOo6pbInneflUdmq7YvSVqhpPs5zdBvLnteltQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-replace-supers" "^7.5.5" + +"@babel/plugin-transform-parameters@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.4.tgz#7556cf03f318bd2719fe4c922d2d808be5571e16" + integrity sha512-oMh5DUO1V63nZcu/ZVLQFqiihBGo4OpxJxR1otF50GMeCLiRx5nUdtokd+u9SuVJrvvuIh9OosRFPP4pIPnwmw== + dependencies: + "@babel/helper-call-delegate" "^7.4.4" + "@babel/helper-get-function-arity" "^7.0.0" + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-property-literals@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.2.0.tgz#03e33f653f5b25c4eb572c98b9485055b389e905" + integrity sha512-9q7Dbk4RhgcLp8ebduOpCbtjh7C0itoLYHXd9ueASKAG/is5PQtMR5VJGka9NKqGhYEGn5ITahd4h9QeBMylWQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-react-jsx@^7.0.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.7.0.tgz#834b0723ba78cd4d24d7d629300c2270f516d0b7" + integrity sha512-mXhBtyVB1Ujfy+0L6934jeJcSXj/VCg6whZzEcgiiZHNS0PGC7vUCsZDQCxxztkpIdF+dY1fUMcjAgEOC3ZOMQ== + dependencies: + "@babel/helper-builder-react-jsx" "^7.7.0" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-jsx" "^7.2.0" + +"@babel/plugin-transform-regenerator@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.7.0.tgz#f1b20b535e7716b622c99e989259d7dd942dd9cc" + integrity sha512-AXmvnC+0wuj/cFkkS/HFHIojxH3ffSXE+ttulrqWjZZRaUOonfJc60e1wSNT4rV8tIunvu/R3wCp71/tLAa9xg== + dependencies: + regenerator-transform "^0.14.0" + +"@babel/plugin-transform-reserved-words@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.2.0.tgz#4792af87c998a49367597d07fedf02636d2e1634" + integrity sha512-fz43fqW8E1tAB3DKF19/vxbpib1fuyCwSPE418ge5ZxILnBhWyhtPgz8eh1RCGGJlwvksHkyxMxh0eenFi+kFw== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-shorthand-properties@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz#6333aee2f8d6ee7e28615457298934a3b46198f0" + integrity sha512-QP4eUM83ha9zmYtpbnyjTLAGKQritA5XW/iG9cjtuOI8s1RuL/3V6a3DeSHfKutJQ+ayUfeZJPcnCYEQzaPQqg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-spread@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.6.2.tgz#fc77cf798b24b10c46e1b51b1b88c2bf661bb8dd" + integrity sha512-DpSvPFryKdK1x+EDJYCy28nmAaIMdxmhot62jAXF/o99iA33Zj2Lmcp3vDmz+MUh0LNYVPvfj5iC3feb3/+PFg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-sticky-regex@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz#a1e454b5995560a9c1e0d537dfc15061fd2687e1" + integrity sha512-KKYCoGaRAf+ckH8gEL3JHUaFVyNHKe3ASNsZ+AlktgHevvxGigoIttrEJb8iKN03Q7Eazlv1s6cx2B2cQ3Jabw== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-regex" "^7.0.0" + +"@babel/plugin-transform-template-literals@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.4.4.tgz#9d28fea7bbce637fb7612a0750989d8321d4bcb0" + integrity sha512-mQrEC4TWkhLN0z8ygIvEL9ZEToPhG5K7KDW3pzGqOfIGZ28Jb0POUkeWcoz8HnHvhFy6dwAT1j8OzqN8s804+g== + dependencies: + "@babel/helper-annotate-as-pure" "^7.0.0" + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-typeof-symbol@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.2.0.tgz#117d2bcec2fbf64b4b59d1f9819894682d29f2b2" + integrity sha512-2LNhETWYxiYysBtrBTqL8+La0jIoQQnIScUJc74OYvUGRmkskNY4EzLCnjHBzdmb38wqtTaixpo1NctEcvMDZw== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-typescript@^7.4.5": + version "7.7.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.7.2.tgz#eb9f14c516b5d36f4d6f3a9d7badae6d0fc313d4" + integrity sha512-UWhDaJRqdPUtdK1s0sKYdoRuqK0NepjZto2UZltvuCgMoMZmdjhgz5hcRokie/3aYEaSz3xvusyoayVaq4PjRg== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.7.0" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-typescript" "^7.2.0" + +"@babel/plugin-transform-unicode-regex@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.7.0.tgz#743d9bcc44080e3cc7d49259a066efa30f9187a3" + integrity sha512-RrThb0gdrNwFAqEAAx9OWgtx6ICK69x7i9tCnMdVrxQwSDp/Abu9DXFU5Hh16VP33Rmxh04+NGW28NsIkFvFKA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.7.0" + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/preset-env@^7.0.0": + version "7.7.1" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.7.1.tgz#04a2ff53552c5885cf1083e291c8dd5490f744bb" + integrity sha512-/93SWhi3PxcVTDpSqC+Dp4YxUu3qZ4m7I76k0w73wYfn7bGVuRIO4QUz95aJksbS+AD1/mT1Ie7rbkT0wSplaA== + dependencies: + "@babel/helper-module-imports" "^7.7.0" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-proposal-async-generator-functions" "^7.7.0" + "@babel/plugin-proposal-dynamic-import" "^7.7.0" + "@babel/plugin-proposal-json-strings" "^7.2.0" + "@babel/plugin-proposal-object-rest-spread" "^7.6.2" + "@babel/plugin-proposal-optional-catch-binding" "^7.2.0" + "@babel/plugin-proposal-unicode-property-regex" "^7.7.0" + "@babel/plugin-syntax-async-generators" "^7.2.0" + "@babel/plugin-syntax-dynamic-import" "^7.2.0" + "@babel/plugin-syntax-json-strings" "^7.2.0" + "@babel/plugin-syntax-object-rest-spread" "^7.2.0" + "@babel/plugin-syntax-optional-catch-binding" "^7.2.0" + "@babel/plugin-syntax-top-level-await" "^7.7.0" + "@babel/plugin-transform-arrow-functions" "^7.2.0" + "@babel/plugin-transform-async-to-generator" "^7.7.0" + "@babel/plugin-transform-block-scoped-functions" "^7.2.0" + "@babel/plugin-transform-block-scoping" "^7.6.3" + "@babel/plugin-transform-classes" "^7.7.0" + "@babel/plugin-transform-computed-properties" "^7.2.0" + "@babel/plugin-transform-destructuring" "^7.6.0" + "@babel/plugin-transform-dotall-regex" "^7.7.0" + "@babel/plugin-transform-duplicate-keys" "^7.5.0" + "@babel/plugin-transform-exponentiation-operator" "^7.2.0" + "@babel/plugin-transform-for-of" "^7.4.4" + "@babel/plugin-transform-function-name" "^7.7.0" + "@babel/plugin-transform-literals" "^7.2.0" + "@babel/plugin-transform-member-expression-literals" "^7.2.0" + "@babel/plugin-transform-modules-amd" "^7.5.0" + "@babel/plugin-transform-modules-commonjs" "^7.7.0" + "@babel/plugin-transform-modules-systemjs" "^7.7.0" + "@babel/plugin-transform-modules-umd" "^7.7.0" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.7.0" + "@babel/plugin-transform-new-target" "^7.4.4" + "@babel/plugin-transform-object-super" "^7.5.5" + "@babel/plugin-transform-parameters" "^7.4.4" + "@babel/plugin-transform-property-literals" "^7.2.0" + "@babel/plugin-transform-regenerator" "^7.7.0" + "@babel/plugin-transform-reserved-words" "^7.2.0" + "@babel/plugin-transform-shorthand-properties" "^7.2.0" + "@babel/plugin-transform-spread" "^7.6.2" + "@babel/plugin-transform-sticky-regex" "^7.2.0" + "@babel/plugin-transform-template-literals" "^7.4.4" + "@babel/plugin-transform-typeof-symbol" "^7.2.0" + "@babel/plugin-transform-unicode-regex" "^7.7.0" + "@babel/types" "^7.7.1" + browserslist "^4.6.0" + core-js-compat "^3.1.1" + invariant "^2.2.2" + js-levenshtein "^1.1.3" + semver "^5.5.0" + +"@babel/template@^7.0.0", "@babel/template@^7.2.2", "@babel/template@^7.7.0": + version "7.7.0" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.7.0.tgz#4fadc1b8e734d97f56de39c77de76f2562e597d0" + integrity sha512-OKcwSYOW1mhWbnTBgQY5lvg1Fxg+VyfQGjcBduZFljfc044J5iDlnDSfhQ867O17XHiSCxYHUxHg2b7ryitbUQ== + dependencies: + "@babel/code-frame" "^7.0.0" + "@babel/parser" "^7.7.0" + "@babel/types" "^7.7.0" + +"@babel/traverse@^7.0.0", "@babel/traverse@^7.2.3", "@babel/traverse@^7.7.0", "@babel/traverse@^7.7.2": + version "7.7.2" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.7.2.tgz#ef0a65e07a2f3c550967366b3d9b62a2dcbeae09" + integrity sha512-TM01cXib2+rgIZrGJOLaHV/iZUAxf4A0dt5auY6KNZ+cm6aschuJGqKJM3ROTt3raPUdIDk9siAufIFEleRwtw== + dependencies: + "@babel/code-frame" "^7.5.5" + "@babel/generator" "^7.7.2" + "@babel/helper-function-name" "^7.7.0" + "@babel/helper-split-export-declaration" "^7.7.0" + "@babel/parser" "^7.7.2" + "@babel/types" "^7.7.2" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.13" + +"@babel/types@^7.0.0", "@babel/types@^7.3.3", "@babel/types@^7.7.0", "@babel/types@^7.7.1", "@babel/types@^7.7.2": + version "7.7.2" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.7.2.tgz#550b82e5571dcd174af576e23f0adba7ffc683f7" + integrity sha512-YTf6PXoh3+eZgRCBzzP25Bugd2ngmpQVrk7kXX0i5N9BO7TFBtIgZYs7WtxtOGs8e6A4ZI7ECkbBCEHeXocvOA== + dependencies: + esutils "^2.0.2" + lodash "^4.17.13" + to-fast-properties "^2.0.0" + +"@iarna/toml@^2.2.0": + version "2.2.3" + resolved "https://registry.yarnpkg.com/@iarna/toml/-/toml-2.2.3.tgz#f060bf6eaafae4d56a7dac618980838b0696e2ab" + integrity sha512-FmuxfCuolpLl0AnQ2NHSzoUKWEJDFl63qXjzdoWBVyFCXzMGm1spBzk7LeHNoVCiWCF7mRVms9e6jEV9+MoPbg== + +"@nodelib/fs.scandir@2.1.3": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b" + integrity sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw== + dependencies: + "@nodelib/fs.stat" "2.0.3" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.3", "@nodelib/fs.stat@^2.0.2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz#34dc5f4cabbc720f4e60f75a747e7ecd6c175bd3" + integrity sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz#011b9202a70a6366e436ca5c065844528ab04976" + integrity sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ== + dependencies: + "@nodelib/fs.scandir" "2.1.3" + fastq "^1.6.0" + +"@parcel/babel-preset-env@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/babel-preset-env/-/babel-preset-env-2.0.0-alpha.3.1.tgz#57de8cac436023f16a74858904a9fab1b7886714" + integrity sha512-OXxuA+B113MDWMuOrsIbMBZOZ3uVs+jHseNYae6MT34Op63wistpP9Xlzv8DBChgbZyPS7bPpYYyf8ZK5Da0LA== + dependencies: + "@babel/preset-env" "^7.0.0" + semver "^5.4.1" + +"@parcel/bundler-default@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/bundler-default/-/bundler-default-2.0.0-alpha.3.1.tgz#33f318d826989f517e4753c249fdf807de339433" + integrity sha512-p21dHAEn5ewFZ6ZhDL8faKnBobrPVO/3O/uo4yxedQp4Lmf7pVGAo6C9rZEM2HB7pJjCeQBmLVsGdFn0mMZT8w== + dependencies: + "@parcel/plugin" "^2.0.0-alpha.3.1" + "@parcel/utils" "^2.0.0-alpha.3.1" + nullthrows "^1.1.1" + +"@parcel/cache@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/cache/-/cache-2.0.0-alpha.3.1.tgz#4d3db941a9ffa2b788cf52009bfa9069fa2aafdf" + integrity sha512-KI+mj/YEFxZyCCTcUoyXrS4nEI0CD/HvaayuNt/5QuAZmkJ3iDw0vo5nS8xC9VGL94cZZHG4qZWDigQvHI5vZQ== + dependencies: + "@parcel/logger" "^2.0.0-alpha.3.1" + "@parcel/utils" "^2.0.0-alpha.3.1" + +"@parcel/codeframe@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/codeframe/-/codeframe-2.0.0-alpha.3.1.tgz#0dd4b2f6c2f1fdb283c5b407ae7b96ce94cd4418" + integrity sha512-Y7orGAw9qvrH86RBxpSuidIfR13uqoH/RoeBr3vq4CIYFW6K6JunEWTGAstV5hpuY6pzk7mv2xxhNCUkIYBIFg== + dependencies: + chalk "^2.4.2" + emphasize "^2.1.0" + +"@parcel/config-default@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/config-default/-/config-default-2.0.0-alpha.3.1.tgz#459e9b28001fa8de2631b4ead4e3292d093ced17" + integrity sha512-tQfvLIzAuASnyoUX0cD2jBr8bcpsZMeFCeZWAWu715b9dHmZ3FHlD6tzsV18O6V+7lMCqJfLDg3vPBGvDA79mA== + dependencies: + "@parcel/bundler-default" "^2.0.0-alpha.3.1" + "@parcel/namer-default" "^2.0.0-alpha.3.1" + "@parcel/optimizer-cssnano" "^2.0.0-alpha.3.1" + "@parcel/optimizer-data-url" "^2.0.0-alpha.3.1" + "@parcel/optimizer-htmlnano" "^2.0.0-alpha.3.1" + "@parcel/optimizer-terser" "^2.0.0-alpha.3.1" + "@parcel/packager-css" "^2.0.0-alpha.3.1" + "@parcel/packager-html" "^2.0.0-alpha.3.1" + "@parcel/packager-js" "^2.0.0-alpha.3.1" + "@parcel/packager-raw" "^2.0.0-alpha.3.1" + "@parcel/packager-ts" "^2.0.0-alpha.3.1" + "@parcel/reporter-cli" "^2.0.0-alpha.3.1" + "@parcel/reporter-dev-server" "^2.0.0-alpha.3.1" + "@parcel/reporter-hmr-server" "^2.0.0-alpha.3.1" + "@parcel/resolver-default" "^2.0.0-alpha.3.1" + "@parcel/runtime-browser-hmr" "^2.0.0-alpha.3.1" + "@parcel/runtime-js" "^2.0.0-alpha.3.1" + "@parcel/runtime-react-refresh" "^2.0.0-alpha.3.1" + "@parcel/transformer-babel" "^2.0.0-alpha.3.1" + "@parcel/transformer-coffeescript" "^2.0.0-alpha.3.1" + "@parcel/transformer-css" "^2.0.0-alpha.3.1" + "@parcel/transformer-graphql" "^2.0.0-alpha.3.1" + "@parcel/transformer-html" "^2.0.0-alpha.3.1" + "@parcel/transformer-inline-string" "^2.0.0-alpha.3.1" + "@parcel/transformer-js" "^2.0.0-alpha.3.1" + "@parcel/transformer-json" "^2.0.0-alpha.3.1" + "@parcel/transformer-less" "^2.0.0-alpha.3.1" + "@parcel/transformer-postcss" "^2.0.0-alpha.3.1" + "@parcel/transformer-posthtml" "^2.0.0-alpha.3.1" + "@parcel/transformer-pug" "^2.0.0-alpha.3.1" + "@parcel/transformer-raw" "^2.0.0-alpha.3.1" + "@parcel/transformer-react-refresh-babel" "^2.0.0-alpha.3.1" + "@parcel/transformer-react-refresh-wrap" "^2.0.0-alpha.3.1" + "@parcel/transformer-sass" "^2.0.0-alpha.3.1" + "@parcel/transformer-stylus" "^2.0.0-alpha.3.1" + "@parcel/transformer-sugarss" "^2.0.0-alpha.3.1" + "@parcel/transformer-toml" "^2.0.0-alpha.3.1" + "@parcel/transformer-typescript-types" "^2.0.0-alpha.3.1" + "@parcel/transformer-yaml" "^2.0.0-alpha.3.1" + +"@parcel/core@^2.0.0-alpha.3.2": + version "2.0.0-alpha.3.2" + resolved "https://registry.yarnpkg.com/@parcel/core/-/core-2.0.0-alpha.3.2.tgz#28ef7b464556803f0454fc46316530d1cd4524ef" + integrity sha512-Nnr4GOmx0mzUhSLu6MvBpPJDA3YhgWPDwpw1uH/80vRXqLYrX1sZCnOYjGGhoWi7VrYjoHVak+FZLrZrhUlGmw== + dependencies: + "@parcel/cache" "^2.0.0-alpha.3.1" + "@parcel/diagnostic" "^2.0.0-alpha.3.1" + "@parcel/events" "^2.0.0-alpha.3.1" + "@parcel/fs" "^2.0.0-alpha.3.1" + "@parcel/logger" "^2.0.0-alpha.3.1" + "@parcel/package-manager" "^2.0.0-alpha.3.1" + "@parcel/plugin" "^2.0.0-alpha.3.1" + "@parcel/source-map" "^2.0.0-alpha.3.1" + "@parcel/types" "^2.0.0-alpha.3.1" + "@parcel/utils" "^2.0.0-alpha.3.1" + "@parcel/workers" "^2.0.0-alpha.3.1" + abortcontroller-polyfill "^1.1.9" + browserslist "^4.6.6" + clone "^2.1.1" + dotenv "^7.0.0" + dotenv-expand "^5.1.0" + json5 "^1.0.1" + micromatch "^4.0.2" + nullthrows "^1.1.1" + pirates "^4.0.0" + semver "^5.4.1" + +"@parcel/diagnostic@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/diagnostic/-/diagnostic-2.0.0-alpha.3.1.tgz#005376248503ad40e7c84f004e3d2b69e7c17bf7" + integrity sha512-45kRMFXFu5LZm77dJ8SJdPF4RdpP+zCBC2Q/ebXWvbgLKJOyapAtnFFvdwCS4xfbvL2xOrC4gEsP0SCvZTVKWQ== + dependencies: + json-source-map "^0.6.1" + nullthrows "^1.1.1" + +"@parcel/events@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/events/-/events-2.0.0-alpha.3.1.tgz#a287e415d12920745b5ac6e11b86c2e51d44a8ee" + integrity sha512-s3f54ppFRTxHNZ4cMaqJBf6qYWHEI/Jo6pD//4XU3VTMLyUC9pAj+rEVx7vZi7fAye7FKC5aLsrvFp4dby/pTA== + +"@parcel/fs@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/fs/-/fs-2.0.0-alpha.3.1.tgz#06fdf709f1412727e6ebd267ee42f5a9119aa0b4" + integrity sha512-DHXGRX/D9F2RgKecN6Fh7KmqLWD+IQxEraURF4hxw/QCfdQiUaobPS65I3VG7GLRhTeEXMjDibPF5902FJiQuQ== + dependencies: + "@parcel/utils" "^2.0.0-alpha.3.1" + "@parcel/watcher" "^2.0.0-alpha.4" + "@parcel/workers" "^2.0.0-alpha.3.1" + mkdirp "^0.5.1" + ncp "^2.0.0" + nullthrows "^1.1.1" + rimraf "^2.6.2" + +"@parcel/logger@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/logger/-/logger-2.0.0-alpha.3.1.tgz#f0ea5b912419bc2e2aaf78cbbb8dff53d727cfa0" + integrity sha512-+Lyk1rtiyezoZor6yKq4lnbfIIQD0pdSSPhomKOa+yTpnWZVLjNZ/QJ+Q4PocJtN+VLOzw23nbPsTKeDTAYtEQ== + dependencies: + "@parcel/diagnostic" "^2.0.0-alpha.3.1" + "@parcel/events" "^2.0.0-alpha.3.1" + +"@parcel/markdown-ansi@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/markdown-ansi/-/markdown-ansi-2.0.0-alpha.3.1.tgz#b06db6c592c3bcd1a6163efaf3b625d686c973c3" + integrity sha512-e88oynbkLr/l8mbANhtlxwfTFV0O7QZrKz9g+WTWOdouJZz/vEYb1Au4BjdyMiT+H0WXtlFSAJC6XzIaMeZxZA== + dependencies: + chalk "^2.4.2" + +"@parcel/namer-default@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/namer-default/-/namer-default-2.0.0-alpha.3.1.tgz#c74a929166fb35ce1a72d65fc5e5a07262327f0e" + integrity sha512-w3zB+pvdWSa+an3sYLE74+b2Es1JSX+lcUFM2I0fL996GL0EZiu4teYiN0Bet0sxBlTJdrrnxhIAEGzVtA9B+w== + dependencies: + "@parcel/plugin" "^2.0.0-alpha.3.1" + nullthrows "^1.1.1" + +"@parcel/optimizer-cssnano@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/optimizer-cssnano/-/optimizer-cssnano-2.0.0-alpha.3.1.tgz#09e8a7fe55a5a16b5a7f35874334dbfcb7b899e8" + integrity sha512-t/rBVgOt6wJ6jd0C7+D0zXcUWSHMPh3YnvcM516INtZJ7t/RrQZM5Z9+hUvD8u1nEDzAKqblLvgAn2q7enNP9g== + dependencies: + "@parcel/plugin" "^2.0.0-alpha.3.1" + cssnano "^4.1.10" + postcss "^7.0.5" + +"@parcel/optimizer-data-url@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/optimizer-data-url/-/optimizer-data-url-2.0.0-alpha.3.1.tgz#16e9eac5e6ce87afa6191135766c6484006afc1f" + integrity sha512-1PXp/kjRELe8ie7DHYz3QDDTumaJs3a8WFb3DzYM87VdgB23YEXvoaFgtM04QW17zF8rnH2PqT6HnPeJcYe3bg== + dependencies: + "@parcel/plugin" "^2.0.0-alpha.3.1" + "@parcel/utils" "^2.0.0-alpha.3.1" + isbinaryfile "^4.0.2" + mime "^2.4.4" + +"@parcel/optimizer-htmlnano@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/optimizer-htmlnano/-/optimizer-htmlnano-2.0.0-alpha.3.1.tgz#3d726b24eea653e25c3d92a4df02c3789d3aeed7" + integrity sha512-Qpw+KLlVhfi/F5DX5mCpYTjJ9vvVrGUSjM+TG6rOcpkPjZnE/7zYtck5Z9IHc78/dUjwFthMQR9R3dBi6aCqOA== + dependencies: + "@parcel/plugin" "^2.0.0-alpha.3.1" + "@parcel/utils" "^2.0.0-alpha.3.1" + htmlnano "^0.2.2" + nullthrows "^1.1.1" + posthtml "^0.11.3" + +"@parcel/optimizer-terser@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/optimizer-terser/-/optimizer-terser-2.0.0-alpha.3.1.tgz#633acdcf4b0817da9dc3d61e955ea2edbba7f9b3" + integrity sha512-gNs2ubWubwsARLYexqztYzw6xwvDUzD4HHkIEAg3WIVUSXyBeaaZXiCzBM2wjzLh14WXFc6BmlHSlqeFBNCe/g== + dependencies: + "@parcel/plugin" "^2.0.0-alpha.3.1" + "@parcel/source-map" "^2.0.0-alpha.3.1" + "@parcel/utils" "^2.0.0-alpha.3.1" + nullthrows "^1.1.1" + terser "^4.0.0" + +"@parcel/package-manager@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/package-manager/-/package-manager-2.0.0-alpha.3.1.tgz#e413d0385ea5fcdcfd391bffd836fd742d8cf277" + integrity sha512-5rU0A7cMoNpiZx3fJh9cL+eDqOe5jlSBrFuEp864ZcKTkCoiyysZPza0Hmm368Q0nclcm9ueaR/Dgm2WXgVK7g== + dependencies: + "@parcel/fs" "^2.0.0-alpha.3.1" + "@parcel/logger" "^2.0.0-alpha.3.1" + "@parcel/utils" "^2.0.0-alpha.3.1" + "@parcel/workers" "^2.0.0-alpha.3.1" + command-exists "^1.2.6" + cross-spawn "^6.0.4" + nullthrows "^1.1.1" + resolve "^1.12.0" + split2 "^3.1.1" + +"@parcel/packager-css@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/packager-css/-/packager-css-2.0.0-alpha.3.1.tgz#210c176c5fdc5e99682d8df59429586137fee70f" + integrity sha512-IvQ8PBC0fPlHvc0SM1BINqNwMqoYS3/yeuxTs0DJ+gnEmbcSwOsxhJT7LoAOne3LUjGjOVmvmHXpItCmqXciiQ== + dependencies: + "@parcel/plugin" "^2.0.0-alpha.3.1" + "@parcel/utils" "^2.0.0-alpha.3.1" + +"@parcel/packager-html@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/packager-html/-/packager-html-2.0.0-alpha.3.1.tgz#5f7c2c05cea2f8ffe3a76444839c5f7e1ed91d99" + integrity sha512-tpM20z1OUp1J9q8u+aJb61f622vI4J+nGNhVYN6hUQpZLYHWbPYvgms36MCr7uSQrhUZSDmdWCSEKeyHGy0Ltg== + dependencies: + "@parcel/plugin" "^2.0.0-alpha.3.1" + "@parcel/types" "^2.0.0-alpha.3.1" + "@parcel/utils" "^2.0.0-alpha.3.1" + nullthrows "^1.1.1" + posthtml "^0.11.3" + +"@parcel/packager-js@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/packager-js/-/packager-js-2.0.0-alpha.3.1.tgz#3848224646a3f77c69966bab9e3490a1f52f5883" + integrity sha512-NpsSXFMV37lklq1m+YOnz2x066ePpJ7mibeDm8zev3cF7Gev0AH8f9zUChV2lMBNdRUnPTKz4ZVNnyDXt4KhIA== + dependencies: + "@parcel/plugin" "^2.0.0-alpha.3.1" + "@parcel/scope-hoisting" "^2.0.0-alpha.3.1" + "@parcel/source-map" "^2.0.0-alpha.3.1" + "@parcel/utils" "^2.0.0-alpha.3.1" + +"@parcel/packager-raw@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/packager-raw/-/packager-raw-2.0.0-alpha.3.1.tgz#789d9c354f3e6835ef19b8fb725f42cd0749837e" + integrity sha512-TGyXie5wiwYr4nYqqH606gGmf60/ch3f3MxkCktpaAdKxZLs4ku7io1MUQlg6y7ft7AuCO8+5CNw+A0m37uDyw== + dependencies: + "@parcel/plugin" "^2.0.0-alpha.3.1" + +"@parcel/packager-ts@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/packager-ts/-/packager-ts-2.0.0-alpha.3.1.tgz#c50235d919050fbfaa121578116c4bdbf7109e89" + integrity sha512-tasZk+79dfwiHdgIec6XWiiDM0+Bc1sndtAcplvzbPbFkgViZZZjGu3103uC/giUbCZd+P8mwgt4I+aFjc1yDA== + dependencies: + "@parcel/plugin" "^2.0.0-alpha.3.1" + +"@parcel/plugin@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/plugin/-/plugin-2.0.0-alpha.3.1.tgz#cf0aa095ff6831ebfb722eea5395c867cad36928" + integrity sha512-Wbo4dXtVRZXP1S9Scii46fE6MeHvZjw6eS7/WLhiapvsthWjXQlljLfbjA5ih+6poQv7jgJLUlwZDPxKcHmH8Q== + dependencies: + "@parcel/types" "^2.0.0-alpha.3.1" + +"@parcel/reporter-cli@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/reporter-cli/-/reporter-cli-2.0.0-alpha.3.1.tgz#596fbd2ccf92472443795a950d6d5e8a5426b9c3" + integrity sha512-pdqlksBEuL6FPa+q5Y9jcQH2csxWUNzf8NDK42RnGNRPWnXfJHviErrvCidscaCbFWlgO/LOjyFQ0QxrqbBtjA== + dependencies: + "@parcel/events" "^2.0.0-alpha.3.1" + "@parcel/plugin" "^2.0.0-alpha.3.1" + "@parcel/types" "^2.0.0-alpha.3.1" + "@parcel/utils" "^2.0.0-alpha.3.1" + cli-spinners "^2.0.0" + filesize "^3.6.0" + grapheme-breaker "^0.3.2" + ink "^2.1.1" + ink-spinner "^3.0.1" + nullthrows "^1.1.1" + react "^16.7.0" + +"@parcel/reporter-dev-server@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/reporter-dev-server/-/reporter-dev-server-2.0.0-alpha.3.1.tgz#751feb2d1821aefc39b4e3ade59d40b4b9a58191" + integrity sha512-orZD40KB6aMqBGaX4TibICMeSgGsGsMUnOMjPAGUlYpW3Z50cu4H/bPcJELVsOQTcRsEnW+f4SX7e1qNUM2+oQ== + dependencies: + "@parcel/plugin" "^2.0.0-alpha.3.1" + "@parcel/utils" "^2.0.0-alpha.3.1" + connect "^3.7.0" + ejs "^2.6.1" + http-proxy-middleware "^0.19.1" + mime "^2.4.4" + +"@parcel/reporter-hmr-server@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/reporter-hmr-server/-/reporter-hmr-server-2.0.0-alpha.3.1.tgz#e420be15ab7e5e4ad1c59cd0286801ae408b54ee" + integrity sha512-14JfRPwIOo5viexaZwJqNbrtW6ZC4abmcA6bnTdAPkQQkIuaR01vxyToCU2ZZp9m+grg/9KXBukyC9HIQuqd4A== + dependencies: + "@parcel/plugin" "^2.0.0-alpha.3.1" + "@parcel/reporter-cli" "^2.0.0-alpha.3.1" + "@parcel/utils" "^2.0.0-alpha.3.1" + ws "^6.2.0" + +"@parcel/resolver-default@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/resolver-default/-/resolver-default-2.0.0-alpha.3.1.tgz#d77efc9de06e3d5419848ab8d5e71ac5c7b4783e" + integrity sha512-/m/PicKKalGyYuUh6kgornk6X59gZNtNYPrjFhW2LVlr0+UxrK/QmreI/6GoIrrOfoIQCmz9e9tM2Yh/M22wjg== + dependencies: + "@parcel/plugin" "^2.0.0-alpha.3.1" + "@parcel/utils" "^2.0.0-alpha.3.1" + micromatch "^3.0.4" + node-libs-browser "^2.1.0" + +"@parcel/runtime-browser-hmr@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/runtime-browser-hmr/-/runtime-browser-hmr-2.0.0-alpha.3.1.tgz#b372d809777f5c76b2f44c16b706e4fb495fe18a" + integrity sha512-NPmxw+nLnx1boTwJdPMXYXYumb8GXk423Xo2uZaf7VL95gr+CZf7nod1kDn2XEQYgWDFCrNKR5BqcoSX32fnYw== + dependencies: + "@parcel/plugin" "^2.0.0-alpha.3.1" + "@parcel/utils" "^2.0.0-alpha.3.1" + +"@parcel/runtime-js@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/runtime-js/-/runtime-js-2.0.0-alpha.3.1.tgz#298ce01e0ac3d590170c8189bb0e4387fee66046" + integrity sha512-Q2v2auDNEiLs5Vmdv3u4lBgN+PrpvbAUzi6U1SG65UhDIUWL1Z1qumBctwXV92PoQoi3wwzR1BtV/ErN3cJoJQ== + dependencies: + "@parcel/plugin" "^2.0.0-alpha.3.1" + "@parcel/utils" "^2.0.0-alpha.3.1" + nullthrows "^1.1.1" + +"@parcel/runtime-react-refresh@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/runtime-react-refresh/-/runtime-react-refresh-2.0.0-alpha.3.1.tgz#0514efdc7721990d86e053db064aa7a26e867ee1" + integrity sha512-ZT5s/laZSSEjCywiXBxuRzMluWpk8k/gjk3wx0FHYK6Win2Lbi/ViKuOAM4qmNKKSMUZUJPQKfdNMc+Jv3miOg== + dependencies: + "@parcel/plugin" "^2.0.0-alpha.3.1" + react-refresh "^0.6.0" + +"@parcel/scope-hoisting@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/scope-hoisting/-/scope-hoisting-2.0.0-alpha.3.1.tgz#60e0387a416acca780b9c53496303c0ff46f9efe" + integrity sha512-GFdBGxUNDLQcQ+jAm+hp+Zn9faxvfY7qnmd3pCAHGgn6MHC8THJ8VSM0E6MobG8G5Qi6iYU0y+YvQ6rjrNiulw== + dependencies: + "@babel/generator" "^7.3.3" + "@babel/parser" "^7.0.0" + "@babel/template" "^7.2.2" + "@babel/traverse" "^7.2.3" + "@babel/types" "^7.3.3" + "@parcel/utils" "^2.0.0-alpha.3.1" + babylon-walk "^1.0.2" + nullthrows "^1.1.1" + +"@parcel/source-map@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/source-map/-/source-map-2.0.0-alpha.3.1.tgz#f47af787afb3a8917145ef838c55e93e462e675e" + integrity sha512-3aL1UwzeJUKryXKvUkSiiVGd2vS6tjqInbQTundEmoOY103uzE4Pyg3RiSRzAFbz+H7CJHnhz/aQdaykGO9IJg== + dependencies: + "@parcel/utils" "^2.0.0-alpha.3.1" + nullthrows "^1.1.1" + source-map "^0.7.3" + +"@parcel/transformer-babel@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/transformer-babel/-/transformer-babel-2.0.0-alpha.3.1.tgz#d962ef4608833e33943198a2126ba34aa3c174b4" + integrity sha512-9NM6huhWNz9i2G32WiP0hzrrUbiLbMDiOnjeTXe+++F0b+WFLvSa7F0AWPcolrElGZoRjXj3tieHgF01gqiZNA== + dependencies: + "@babel/core" "^7.0.0" + "@babel/generator" "^7.0.0" + "@babel/plugin-transform-flow-strip-types" "^7.0.0" + "@babel/plugin-transform-react-jsx" "^7.0.0" + "@babel/plugin-transform-typescript" "^7.4.5" + "@babel/preset-env" "^7.0.0" + "@babel/traverse" "^7.0.0" + "@parcel/babel-preset-env" "^2.0.0-alpha.3.1" + "@parcel/plugin" "^2.0.0-alpha.3.1" + "@parcel/source-map" "^2.0.0-alpha.3.1" + "@parcel/utils" "^2.0.0-alpha.3.1" + browserslist "^4.6.6" + core-js "^3.2.1" + nullthrows "^1.1.1" + semver "^5.4.1" + +"@parcel/transformer-coffeescript@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/transformer-coffeescript/-/transformer-coffeescript-2.0.0-alpha.3.1.tgz#076af4afbeee1f15dfb2dac3059ba55b1ac9211c" + integrity sha512-S6hUsEeeztojZk4Rj7tuWHdOwY7zDWqxF22A3GiRkuDmqC1rGtnZ2snfYiCnC4UAoqB69QkaFpZBdpNltxwz3g== + dependencies: + "@parcel/plugin" "^2.0.0-alpha.3.1" + "@parcel/source-map" "^2.0.0-alpha.3.1" + "@parcel/utils" "^2.0.0-alpha.3.1" + coffeescript "^2.0.3" + nullthrows "^1.1.1" + semver "^5.4.1" + +"@parcel/transformer-css@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/transformer-css/-/transformer-css-2.0.0-alpha.3.1.tgz#dec0378c39490dfbd6fc49a7a036eb22e35941dc" + integrity sha512-oJ3N0acB0O6WQxfwI2D+yjviCm1j3YE7UDULrpqAKciiz65zTt8lMYRinXf9q+grsOcYqEUrosPFlqU5tf1whQ== + dependencies: + "@parcel/plugin" "^2.0.0-alpha.3.1" + postcss "^7.0.5" + postcss-value-parser "^3.3.1" + semver "^5.4.1" + +"@parcel/transformer-graphql@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/transformer-graphql/-/transformer-graphql-2.0.0-alpha.3.1.tgz#c941d8ab223503ea22b7bd108bb8ab6292bb5e0a" + integrity sha512-E1TDgOaL3FV1FqTZ7TsSVScq98nZAjShjM0+SNdJ3Aw3dvN4REIZgzO9qcSufkefS4OOTHfrKXp/r2VhUtHjPw== + dependencies: + "@parcel/plugin" "^2.0.0-alpha.3.1" + +"@parcel/transformer-html@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/transformer-html/-/transformer-html-2.0.0-alpha.3.1.tgz#cfa913692f8abb8ad52f653b2733e1d8d3df23fe" + integrity sha512-FYDeL6iFB0+1EZpM0GTyOo/B2vCNfjEp1Y8X7OOCnuQBuVTW8fb1XI8mFa0RoSfgBx+1vIdaIILQa+qGPvHxtw== + dependencies: + "@parcel/plugin" "^2.0.0-alpha.3.1" + "@parcel/utils" "^2.0.0-alpha.3.1" + nullthrows "^1.1.1" + posthtml "^0.11.3" + posthtml-parser "^0.4.1" + posthtml-render "^1.1.5" + semver "^5.4.1" + +"@parcel/transformer-inline-string@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/transformer-inline-string/-/transformer-inline-string-2.0.0-alpha.3.1.tgz#e41611a9079a053bc8f69abf7982305d1a8281ed" + integrity sha512-NKWm1zEcj3Qq8nna+bSjruwVIlBaNgain5wCPmSRCviFs8KCPNqu0zOiSk6135Gr9fluzGpzefD3eINwlrAyCg== + dependencies: + "@parcel/plugin" "^2.0.0-alpha.3.1" + +"@parcel/transformer-js@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/transformer-js/-/transformer-js-2.0.0-alpha.3.1.tgz#6aea570445ef303824e318d4c916d9739cb4834a" + integrity sha512-9N5p0V/c/gdvXDOMCuCAcYWLGVwjFEBQ31rw3gPNnJyQePZ4icwv2bC8tWJK4V3gynlcTek9hRRHhq69QCNGew== + dependencies: + "@babel/core" "^7.0.0" + "@babel/generator" "^7.0.0" + "@babel/parser" "^7.0.0" + "@babel/plugin-transform-modules-commonjs" "^7.0.0" + "@babel/template" "^7.0.0" + "@babel/traverse" "^7.0.0" + "@babel/types" "^7.0.0" + "@parcel/plugin" "^2.0.0-alpha.3.1" + "@parcel/scope-hoisting" "^2.0.0-alpha.3.1" + "@parcel/source-map" "^2.0.0-alpha.3.1" + "@parcel/utils" "^2.0.0-alpha.3.1" + babylon-walk "^1.0.2" + node-libs-browser "^2.0.0" + nullthrows "^1.1.1" + semver "^5.4.1" + +"@parcel/transformer-json@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/transformer-json/-/transformer-json-2.0.0-alpha.3.1.tgz#dc9d05d59da3158cd63cd5c1137f530378472b46" + integrity sha512-laF4vTyxxdU9ONASbGfWHIy+FoofZMjc0yaJ52SilOdDEa+eIG/UGnetEmml8VsIJStlYH/Qhz3C2XMY2zk/UQ== + dependencies: + "@parcel/plugin" "^2.0.0-alpha.3.1" + json5 "^2.1.0" + +"@parcel/transformer-less@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/transformer-less/-/transformer-less-2.0.0-alpha.3.1.tgz#8a9e29832685621d6cc376d2e566ed21ec3fff1a" + integrity sha512-nsLobEm7uy2YVMWC8hxi1J9IWniJ/UcJMdXfAMy5wQa/1acK4HFpc2xdQhT07sb88HL2qDnqvDEA6Rqs/GYNdQ== + dependencies: + "@parcel/plugin" "^2.0.0-alpha.3.1" + +"@parcel/transformer-postcss@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/transformer-postcss/-/transformer-postcss-2.0.0-alpha.3.1.tgz#a364cb2b1aae4a04419a225ba4a236c3f78b9808" + integrity sha512-ZxUSCBpIXVdK+r7lT6w5nDyvsqic8xRRaM6DthXrRQVV3pQA3YzHFlCV343UY/Hn+N+2AocmG1GrZHi2EP6pyg== + dependencies: + "@parcel/plugin" "^2.0.0-alpha.3.1" + "@parcel/utils" "^2.0.0-alpha.3.1" + css-modules-loader-core "^1.1.0" + nullthrows "^1.1.1" + postcss "^7.0.5" + postcss-value-parser "^3.3.1" + semver "^5.4.1" + +"@parcel/transformer-posthtml@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/transformer-posthtml/-/transformer-posthtml-2.0.0-alpha.3.1.tgz#5557657256529ec00097d1d1250843ee2f9d8ec2" + integrity sha512-v+MFsFY1hS8pjaIwWJDrleEmoPMWdBbzuAkcK3M1b2dVEw+dMihdFIZPccFVS+dN6h27x2N0Zg+kLUOSQczHMg== + dependencies: + "@parcel/plugin" "^2.0.0-alpha.3.1" + nullthrows "^1.1.1" + posthtml "^0.11.3" + posthtml-parser "^0.4.1" + posthtml-render "^1.1.5" + semver "^5.4.1" + +"@parcel/transformer-pug@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/transformer-pug/-/transformer-pug-2.0.0-alpha.3.1.tgz#7a7073e175d20fff3d25e563f60682cc85e62ce6" + integrity sha512-xq6yqzllQuySxkdep7UF75TDIMryiRmP1+0Dksbyjx8X8hmEBbV45TKBoGqzsKkxTeAxPumT4vgqVq/3Mhfv2A== + dependencies: + "@parcel/plugin" "^2.0.0-alpha.3.1" + +"@parcel/transformer-raw@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/transformer-raw/-/transformer-raw-2.0.0-alpha.3.1.tgz#dc5cfdf6e97fd6041cade4e0d2f970d30c39ec89" + integrity sha512-Mh13nyQ+NgQLRbuikxM1NK5Qf5Kk3MaWjDyetY0N+QAtiKVhJF7fYCtRpMpo5z+zRBClq8sLHFMAn61YVZWy6w== + dependencies: + "@parcel/plugin" "^2.0.0-alpha.3.1" + +"@parcel/transformer-react-refresh-babel@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/transformer-react-refresh-babel/-/transformer-react-refresh-babel-2.0.0-alpha.3.1.tgz#86293b7e35e8433ad67e819aa1555c4ffa6f9667" + integrity sha512-d6WeHpGk5zP29g/iKZ+Zf7sZq1XEA6VJ52GXDiY1uh82fVm2x4BHx+j2YBOPXhsKlyi7fBQXTUrxGP623jfZVw== + dependencies: + "@parcel/plugin" "^2.0.0-alpha.3.1" + react-refresh "^0.6.0" + +"@parcel/transformer-react-refresh-wrap@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/transformer-react-refresh-wrap/-/transformer-react-refresh-wrap-2.0.0-alpha.3.1.tgz#c21a095616c12861517a4e6e92ae65c2adb2ac98" + integrity sha512-SMSuWlh2J1mZG5yhG+//sRxuf9wSF2XJfmh8FIiFPkE5KdSnngEI5vcDxUpvzEb7eo6Jjzmz0+80rfeUhOmpMg== + dependencies: + "@babel/generator" "^7.0.0" + "@babel/parser" "^7.0.0" + "@babel/template" "^7.0.0" + "@babel/types" "^7.0.0" + "@parcel/plugin" "^2.0.0-alpha.3.1" + "@parcel/source-map" "^2.0.0-alpha.3.1" + "@parcel/utils" "^2.0.0-alpha.3.1" + react-refresh "^0.6.0" + semver "^5.4.1" + +"@parcel/transformer-sass@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/transformer-sass/-/transformer-sass-2.0.0-alpha.3.1.tgz#bab1209ada685d2290570886e53c7e13adf7f8e6" + integrity sha512-ZElQMiV/Fi4vWQsUNUlfuuK7t+YR7f/ISUvYmKUii5vmnskq4a6UwWqWLT5OuscPk4Zc/QeNctkI33YFAOH3XQ== + dependencies: + "@parcel/fs" "^2.0.0-alpha.3.1" + "@parcel/plugin" "^2.0.0-alpha.3.1" + "@parcel/utils" "^2.0.0-alpha.3.1" + +"@parcel/transformer-stylus@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/transformer-stylus/-/transformer-stylus-2.0.0-alpha.3.1.tgz#5ea4c1fddfa7d63c9c77d47477c9cc53a2c9c471" + integrity sha512-QYyvDESfk6KuPv5qG4M+MdBSrONLYMjbDsHkBF9pMATy3WLyFD2bfwv7eVVHwFnp/zuRnuHy7h2GU9zk//y5tA== + dependencies: + "@parcel/plugin" "^2.0.0-alpha.3.1" + "@parcel/utils" "^2.0.0-alpha.3.1" + +"@parcel/transformer-sugarss@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/transformer-sugarss/-/transformer-sugarss-2.0.0-alpha.3.1.tgz#e12caf92d7ae4d1979ad24bc22c77f4f959abb7e" + integrity sha512-E2I2pBHmALE6Bbu6/X4lfuP3a0JWeLmaJRxtWlVNjWVQwyRIKeEuuUZ70wwl9Gydhv9mBmgDuS9jyPxsCDo3dQ== + dependencies: + "@parcel/plugin" "^2.0.0-alpha.3.1" + postcss "^7.0.5" + +"@parcel/transformer-toml@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/transformer-toml/-/transformer-toml-2.0.0-alpha.3.1.tgz#74e54596c90629882dc3b5bc873f87d986b02539" + integrity sha512-hkOhaUIVvghKuo7pyU3gUYZ+8kJk+lfrIFnbYujwqzys9m0WhAQGELc2syb9IYrD7zVZaeI0hB5cJpnHUodBLQ== + dependencies: + "@parcel/plugin" "^2.0.0-alpha.3.1" + +"@parcel/transformer-typescript-types@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/transformer-typescript-types/-/transformer-typescript-types-2.0.0-alpha.3.1.tgz#41b9db71b144f174da3ccd7687eaf02cf36555be" + integrity sha512-duMzWnq49AOSUU9W18GvdycPw/DSfOzKZcY/znYE65eSmEYgcNgWGI6TaluY52FA0cfgLakUe013KmGGI9tyjA== + dependencies: + "@parcel/plugin" "^2.0.0-alpha.3.1" + "@parcel/source-map" "^2.0.0-alpha.3.1" + "@parcel/ts-utils" "^2.0.0-alpha.3.1" + nullthrows "^1.1.1" + +"@parcel/transformer-yaml@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/transformer-yaml/-/transformer-yaml-2.0.0-alpha.3.1.tgz#90f73de36273b3da066381b0dccd7df5f183aa2f" + integrity sha512-sX+8B111x9q1+BgCPq2w08+nfSvXJ/ijdC+YkpqbKeWkcmHDfXI8esajKWW6xSaeaX6UgNfoZopDCsqUWBAxLA== + dependencies: + "@parcel/plugin" "^2.0.0-alpha.3.1" + +"@parcel/ts-utils@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/ts-utils/-/ts-utils-2.0.0-alpha.3.1.tgz#4d40a7ca8615e90fb8af2b514cfdbd65d3ad25af" + integrity sha512-AaafmGAtiBDtO9Ly3ZvyQViF1FCjHFe97QzIC1HShBmQrzD918LZTH7vAnUjUIDYuudn9Gq/26PfQdPM5dYGzA== + dependencies: + nullthrows "^1.1.1" + +"@parcel/types@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/types/-/types-2.0.0-alpha.3.1.tgz#f73a8a242b6cd820f7c8aa6a0629c505314b5bc0" + integrity sha512-+RrfckMkA9BQtR/O987gwD/1fXWeMd5v8k4pBBsmSHtLh7ASnoViRkg9drIQJs6uU17uKgvYNsSYwUNxJzf+0Q== + +"@parcel/utils@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/utils/-/utils-2.0.0-alpha.3.1.tgz#837f68666640c118bd57ac0a4ccea72c9976d815" + integrity sha512-8j3Sbp3J2ahR/MZREwVYYPEvf3LDjFkb1ZA2bq3PljWc+evDNt0ofunP1fBH9w/GvJEtPSx4bu1Z8mINTA/d4Q== + dependencies: + "@iarna/toml" "^2.2.0" + "@parcel/codeframe" "^2.0.0-alpha.3.1" + "@parcel/diagnostic" "^2.0.0-alpha.3.1" + "@parcel/logger" "^2.0.0-alpha.3.1" + "@parcel/markdown-ansi" "^2.0.0-alpha.3.1" + ansi-html "^0.0.7" + clone "^2.1.1" + deasync "^0.1.14" + fast-glob "^3.0.4" + is-glob "^4.0.0" + is-url "^1.2.2" + js-levenshtein "^1.1.6" + json5 "^1.0.1" + micromatch "^4.0.2" + node-forge "^0.8.1" + nullthrows "^1.1.1" + resolve "^1.12.0" + serialize-to-js "^1.1.1" + terser "^3.7.3" + +"@parcel/watcher@^2.0.0-alpha.4": + version "2.0.0-alpha.4" + resolved "https://registry.yarnpkg.com/@parcel/watcher/-/watcher-2.0.0-alpha.4.tgz#d2c88ed7945c00373ab984bfb39b2394f882b794" + integrity sha512-J8Detm6Yeh27lNVr02/bTxqQ5dAs040C9OB1Zs7C4kaDCq/Dx7FVph0aRKDhAiZ0BiSBwgZEh7xmD4ZU844kxA== + dependencies: + bindings "^1.5.0" + node-addon-api "^1.6.2" + prebuild-install "^5.2.5" + +"@parcel/workers@^2.0.0-alpha.3.1": + version "2.0.0-alpha.3.1" + resolved "https://registry.yarnpkg.com/@parcel/workers/-/workers-2.0.0-alpha.3.1.tgz#c93d58ea6fee0ee809c88a2976d67c71e1a0d540" + integrity sha512-XJqRQ5sCFoDFsCupJcUugTOp2RCtrlDuuwyDj9z3migsZ7tDxGhch/ewOy8qePk++aBEIgsNvn0hiERQHK5/0g== + dependencies: + "@parcel/diagnostic" "^2.0.0-alpha.3.1" + "@parcel/logger" "^2.0.0-alpha.3.1" + "@parcel/utils" "^2.0.0-alpha.3.1" + chrome-trace-event "^1.0.2" + nullthrows "^1.1.1" + physical-cpu-count "^2.0.0" + +"@types/prop-types@*": + version "15.7.3" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7" + integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw== + +"@types/q@^1.5.1": + version "1.5.2" + resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8" + integrity sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw== + +"@types/react@^16.8.12", "@types/react@^16.8.6": + version "16.9.11" + resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.11.tgz#70e0b7ad79058a7842f25ccf2999807076ada120" + integrity sha512-UBT4GZ3PokTXSWmdgC/GeCGEJXE5ofWyibCcecRLUVN2ZBpXQGVgQGtG2foS7CrTKFKlQVVswLvf7Js6XA/CVQ== + dependencies: + "@types/prop-types" "*" + csstype "^2.2.0" + +abab@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.3.tgz#623e2075e02eb2d3f2475e49f99c91846467907a" + integrity sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg== + +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + +abortcontroller-polyfill@^1.1.9: + version "1.4.0" + resolved "https://registry.yarnpkg.com/abortcontroller-polyfill/-/abortcontroller-polyfill-1.4.0.tgz#0d5eb58e522a461774af8086414f68e1dda7a6c4" + integrity sha512-3ZFfCRfDzx3GFjO6RAkYx81lPGpUS20ISxux9gLxuKnqafNcFQo59+IoZqpO2WvQlyc287B62HDnDdNYRmlvWA== + +acorn-globals@^4.3.0: + version "4.3.4" + resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.3.4.tgz#9fa1926addc11c97308c4e66d7add0d40c3272e7" + integrity sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A== + dependencies: + acorn "^6.0.1" + acorn-walk "^6.0.1" + +acorn-walk@^6.0.1: + version "6.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.2.0.tgz#123cb8f3b84c2171f1f7fb252615b1c78a6b1a8c" + integrity sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA== + +acorn@^5.0.0: + version "5.7.3" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" + integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== + +acorn@^6.0.1, acorn@^6.0.4: + version "6.3.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.3.0.tgz#0087509119ffa4fc0a0041d1e93a417e68cb856e" + integrity sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA== + +ajv@^6.5.5: + version "6.10.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.2.tgz#d3cea04d6b017b2894ad69040fec8b623eb4bd52" + integrity sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw== + dependencies: + fast-deep-equal "^2.0.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +alphanum-sort@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" + integrity sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM= + +ansi-escapes@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" + integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== + +ansi-escapes@^4.2.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.0.tgz#a4ce2b33d6b214b7950d8595c212f12ac9cc569d" + integrity sha512-EiYhwo0v255HUL6eDyuLrXEkTi7WwVCLAw+SeOQ7M7qdun1z1pum4DEm/nuqIVbPvi9RPPc9k9LbyBv6H0DwVg== + dependencies: + type-fest "^0.8.1" + +ansi-html@^0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/ansi-html/-/ansi-html-0.0.7.tgz#813584021962a9e9e6fd039f940d12f56ca7859e" + integrity sha1-gTWEAhliqenm/QOflA0S9WynhZ4= + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= + +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= + +ansi-regex@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" + integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= + +ansi-styles@^3.2.0, ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +aproba@^1.0.3: + version "1.2.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== + +are-we-there-yet@~1.1.2: + version "1.1.5" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" + integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== + dependencies: + delegates "^1.0.0" + readable-stream "^2.0.6" + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +arr-diff@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= + +arr-flatten@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== + +arr-union@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= + +array-binsearch@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/array-binsearch/-/array-binsearch-1.0.1.tgz#35586dca04ca9ab259c4c4708435acd1babb08ad" + integrity sha1-NVhtygTKmrJZxMRwhDWs0bq7CK0= + +array-equal@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93" + integrity sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM= + +array-unique@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= + +arrify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= + +asn1.js@^4.0.0: + version "4.10.1" + resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" + integrity sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw== + dependencies: + bn.js "^4.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + +asn1@~0.2.3: + version "0.2.4" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" + integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== + dependencies: + safer-buffer "~2.1.0" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= + +assert@^1.1.1: + version "1.5.0" + resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb" + integrity sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA== + dependencies: + object-assign "^4.1.1" + util "0.10.3" + +assign-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= + +astral-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" + integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== + +async-limiter@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" + integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= + +atob@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== + +auto-bind@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/auto-bind/-/auto-bind-2.1.1.tgz#8ae509671ecdfbd5009fc99b0f19ae9c3a2abf50" + integrity sha512-NUwV1i9D3vxxY1KnfZgSZ716d6ovY7o8LfOwLhGIPFBowIb6Ln6DBW64+jCqPzUznel2hRSkQnYQqvh7/ldw8A== + dependencies: + "@types/react" "^16.8.12" + +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= + +aws4@^1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" + integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ== + +babel-plugin-dynamic-import-node@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz#f00f507bdaa3c3e3ff6e7e5e98d90a7acab96f7f" + integrity sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ== + dependencies: + object.assign "^4.1.0" + +babel-runtime@^6.11.6, babel-runtime@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" + integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= + dependencies: + core-js "^2.4.0" + regenerator-runtime "^0.11.0" + +babel-types@^6.15.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" + integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc= + dependencies: + babel-runtime "^6.26.0" + esutils "^2.0.2" + lodash "^4.17.4" + to-fast-properties "^1.0.3" + +babylon-walk@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/babylon-walk/-/babylon-walk-1.0.2.tgz#3b15a5ddbb482a78b4ce9c01c8ba181702d9d6ce" + integrity sha1-OxWl3btIKni0zpwByLoYFwLZ1s4= + dependencies: + babel-runtime "^6.11.6" + babel-types "^6.15.0" + lodash.clone "^4.5.0" + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + +base64-js@^1.0.2: + version "1.3.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1" + integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g== + +base@^0.11.1: + version "0.11.2" + resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== + dependencies: + cache-base "^1.0.1" + class-utils "^0.3.5" + component-emitter "^1.2.1" + define-property "^1.0.0" + isobject "^3.0.1" + mixin-deep "^1.2.0" + pascalcase "^0.1.1" + +bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= + dependencies: + tweetnacl "^0.14.3" + +big.js@^3.1.3: + version "3.2.0" + resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e" + integrity sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q== + +bindings@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" + integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== + dependencies: + file-uri-to-path "1.0.0" + +bl@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/bl/-/bl-3.0.0.tgz#3611ec00579fd18561754360b21e9f784500ff88" + integrity sha512-EUAyP5UHU5hxF8BPT0LKW8gjYLhq1DQIcneOX/pL/m2Alo+OYDQAJlHq+yseMP50Os2nHXOSic6Ss3vSQeyf4A== + dependencies: + readable-stream "^3.0.1" + +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0: + version "4.11.8" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" + integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA== + +boolbase@^1.0.0, boolbase@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" + integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== + dependencies: + arr-flatten "^1.1.0" + array-unique "^0.3.2" + extend-shallow "^2.0.1" + fill-range "^4.0.0" + isobject "^3.0.1" + repeat-element "^1.1.2" + snapdragon "^0.8.1" + snapdragon-node "^2.0.1" + split-string "^3.0.2" + to-regex "^3.0.1" + +braces@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +brfs@^1.2.0: + version "1.6.1" + resolved "https://registry.yarnpkg.com/brfs/-/brfs-1.6.1.tgz#b78ce2336d818e25eea04a0947cba6d4fb8849c3" + integrity sha512-OfZpABRQQf+Xsmju8XE9bDjs+uU4vLREGolP7bDgcpsI17QREyZ4Bl+2KLxxx1kCgA0fAIhKQBaBYh+PEcCqYQ== + dependencies: + quote-stream "^1.0.1" + resolve "^1.1.5" + static-module "^2.2.0" + through2 "^2.0.0" + +brorand@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= + +browser-process-hrtime@^0.1.2: + version "0.1.3" + resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz#616f00faef1df7ec1b5bf9cfe2bdc3170f26c7b4" + integrity sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw== + +browserify-aes@^1.0.0, browserify-aes@^1.0.4: + version "1.2.0" + resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" + integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== + dependencies: + buffer-xor "^1.0.3" + cipher-base "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.3" + inherits "^2.0.1" + safe-buffer "^5.0.1" + +browserify-cipher@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" + integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== + dependencies: + browserify-aes "^1.0.4" + browserify-des "^1.0.0" + evp_bytestokey "^1.0.0" + +browserify-des@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" + integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== + dependencies: + cipher-base "^1.0.1" + des.js "^1.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +browserify-rsa@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524" + integrity sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ= + dependencies: + bn.js "^4.1.0" + randombytes "^2.0.1" + +browserify-sign@^4.0.0: + version "4.0.4" + resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.4.tgz#aa4eb68e5d7b658baa6bf6a57e630cbd7a93d298" + integrity sha1-qk62jl17ZYuqa/alfmMMvXqT0pg= + dependencies: + bn.js "^4.1.1" + browserify-rsa "^4.0.0" + create-hash "^1.1.0" + create-hmac "^1.1.2" + elliptic "^6.0.0" + inherits "^2.0.1" + parse-asn1 "^5.0.0" + +browserify-zlib@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" + integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== + dependencies: + pako "~1.0.5" + +browserslist@^4.0.0, browserslist@^4.6.0, browserslist@^4.6.6, browserslist@^4.7.2: + version "4.7.3" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.7.3.tgz#02341f162b6bcc1e1028e30624815d4924442dc3" + integrity sha512-jWvmhqYpx+9EZm/FxcZSbUZyDEvDTLDi3nSAKbzEkyWvtI0mNSmUosey+5awDW1RUlrgXbQb5A6qY1xQH9U6MQ== + dependencies: + caniuse-lite "^1.0.30001010" + electron-to-chromium "^1.3.306" + node-releases "^1.1.40" + +buffer-equal@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-0.0.1.tgz#91bc74b11ea405bc916bc6aa908faafa5b4aac4b" + integrity sha1-kbx0sR6kBbyRa8aqkI+q+ltKrEs= + +buffer-from@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== + +buffer-xor@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" + integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= + +buffer@^4.3.0: + version "4.9.2" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8" + integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg== + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + isarray "^1.0.0" + +builtin-status-codes@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" + integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= + +cache-base@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== + dependencies: + collection-visit "^1.0.0" + component-emitter "^1.2.1" + get-value "^2.0.6" + has-value "^1.0.0" + isobject "^3.0.1" + set-value "^2.0.0" + to-object-path "^0.3.0" + union-value "^1.0.0" + unset-value "^1.0.0" + +caller-callsite@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" + integrity sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ= + dependencies: + callsites "^2.0.0" + +caller-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" + integrity sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ= + dependencies: + caller-callsite "^2.0.0" + +callsites@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" + integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA= + +camelcase@^5.0.0: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +caniuse-api@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0" + integrity sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw== + dependencies: + browserslist "^4.0.0" + caniuse-lite "^1.0.0" + lodash.memoize "^4.1.2" + lodash.uniq "^4.5.0" + +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001010: + version "1.0.30001011" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001011.tgz#0d6c4549c78c4a800bb043a83ca0cbe0aee6c6e1" + integrity sha512-h+Eqyn/YA6o6ZTqpS86PyRmNWOs1r54EBDcd2NTwwfsXQ8re1B38SnB+p2RKF8OUsyEIjeDU8XGec1RGO/wYCg== + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= + +chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +chalk@^2.0.0, chalk@^2.1.0, chalk@^2.4.0, chalk@^2.4.1, chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chownr@^1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.3.tgz#42d837d5239688d55f303003a508230fa6727142" + integrity sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw== + +chrome-trace-event@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz#234090ee97c7d4ad1a2c4beae27505deffc608a4" + integrity sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ== + dependencies: + tslib "^1.9.0" + +ci-info@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" + integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== + +cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" + integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +class-utils@^0.3.5: + version "0.3.6" + resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== + dependencies: + arr-union "^3.1.0" + define-property "^0.2.5" + isobject "^3.0.0" + static-extend "^0.1.1" + +cli-cursor@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" + integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU= + dependencies: + restore-cursor "^2.0.0" + +cli-spinners@^1.0.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-1.3.1.tgz#002c1990912d0d59580c93bd36c056de99e4259a" + integrity sha512-1QL4544moEsDVH9T/l6Cemov/37iv1RtoKf7NJ04A60+4MREXNfx/QvavbH6QoGdsD4N4Mwy49cmaINR/o2mdg== + +cli-spinners@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.2.0.tgz#e8b988d9206c692302d8ee834e7a85c0144d8f77" + integrity sha512-tgU3fKwzYjiLEQgPMD9Jt+JjHVL9kW93FiIMX/l7rivvOD4/LL0Mf7gda3+4U2KJBloybwgj5KEoQgGRioMiKQ== + +cli-truncate@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-1.1.0.tgz#2b2dfd83c53cfd3572b87fc4d430a808afb04086" + integrity sha512-bAtZo0u82gCfaAGfSNxUdTI9mNyza7D8w4CVCcaOsy7sgwDzvx6ekr6cuWJqY3UGzgnQ1+4wgENup5eIhgxEYA== + dependencies: + slice-ansi "^1.0.0" + string-width "^2.0.0" + +cliui@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" + integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== + dependencies: + string-width "^3.1.0" + strip-ansi "^5.2.0" + wrap-ansi "^5.1.0" + +clone@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" + integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= + +clones@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/clones/-/clones-1.2.0.tgz#b34c872045446a9f264ccceb7731bca05c529b71" + integrity sha512-FXDYw4TjR8wgPZYui2LeTqWh1BLpfQ8lB6upMtlpDF6WlOOxghmTTxWyngdKTgozqBgKnHbTVwTE+hOHqAykuQ== + +coa@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.2.tgz#43f6c21151b4ef2bf57187db0d73de229e3e7ec3" + integrity sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA== + dependencies: + "@types/q" "^1.5.1" + chalk "^2.4.1" + q "^1.1.2" + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= + +coffeescript@^2.0.3: + version "2.4.1" + resolved "https://registry.yarnpkg.com/coffeescript/-/coffeescript-2.4.1.tgz#815fd337df0a34d49e74a98a6ebea9c3e7930f70" + integrity sha512-34GV1aHrsMpTaO3KfMJL40ZNuvKDR/g98THHnE9bQj8HjMaZvSrLik99WWqyMhRtbe8V5hpx5iLgdcSvM/S2wg== + +collection-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= + dependencies: + map-visit "^1.0.0" + object-visit "^1.0.0" + +color-convert@^1.9.0, color-convert@^1.9.1: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + +color-name@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +color-string@^1.5.2: + version "1.5.3" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.3.tgz#c9bbc5f01b58b5492f3d6857459cb6590ce204cc" + integrity sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw== + dependencies: + color-name "^1.0.0" + simple-swizzle "^0.2.2" + +color@^3.0.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/color/-/color-3.1.2.tgz#68148e7f85d41ad7649c5fa8c8106f098d229e10" + integrity sha512-vXTJhHebByxZn3lDvDJYw4lR5+uB3vuoHsuYA5AKuxRVn5wzzIfQKGLBmgdVRHKTJYeK5rvJcHnrd0Li49CFpg== + dependencies: + color-convert "^1.9.1" + color-string "^1.5.2" + +combined-stream@^1.0.6, combined-stream@~1.0.6: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +command-exists@^1.2.6: + version "1.2.8" + resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.8.tgz#715acefdd1223b9c9b37110a149c6392c2852291" + integrity sha512-PM54PkseWbiiD/mMsbvW351/u+dafwTJ0ye2qB60G1aGQP9j3xK2gmMDc+R34L3nDtx4qMCitXT75mkbkGJDLw== + +commander@^2.19.0, commander@^2.20.0: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +component-emitter@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" + integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +concat-stream@~1.6.0: + version "1.6.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +config-chain@^1.1.12: + version "1.1.12" + resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa" + integrity sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA== + dependencies: + ini "^1.3.4" + proto-list "~1.2.1" + +connect@^3.7.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/connect/-/connect-3.7.0.tgz#5d49348910caa5e07a01800b030d0c35f20484f8" + integrity sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ== + dependencies: + debug "2.6.9" + finalhandler "1.1.2" + parseurl "~1.3.3" + utils-merge "1.0.1" + +console-browserify@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" + integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== + +console-control-strings@^1.0.0, console-control-strings@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= + +constants-browserify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" + integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= + +convert-source-map@^1.5.1, convert-source-map@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" + integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== + dependencies: + safe-buffer "~5.1.1" + +copy-descriptor@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= + +core-js-compat@^3.1.1: + version "3.4.1" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.4.1.tgz#e12c5a3ef9fcb50fd9d9a32805bfe674f9139246" + integrity sha512-YdeJI26gLc0CQJ9asLE5obEgBz2I0+CIgnoTbS2T0d5IPQw/OCgCIFR527RmpduxjrB3gSEHoGOCTq9sigOyfw== + dependencies: + browserslist "^4.7.2" + semver "^6.3.0" + +core-js@^2.4.0: + version "2.6.10" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.10.tgz#8a5b8391f8cc7013da703411ce5b585706300d7f" + integrity sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA== + +core-js@^3.2.1: + version "3.4.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.4.1.tgz#76dd6828412900ab27c8ce0b22e6114d7ce21b18" + integrity sha512-KX/dnuY/J8FtEwbnrzmAjUYgLqtk+cxM86hfG60LGiW3MmltIc2yAmDgBgEkfm0blZhUrdr1Zd84J2Y14mLxzg== + +core-util-is@1.0.2, core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= + +cosmiconfig@^5.0.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" + integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== + dependencies: + import-fresh "^2.0.0" + is-directory "^0.3.1" + js-yaml "^3.13.1" + parse-json "^4.0.0" + +create-ecdh@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff" + integrity sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw== + dependencies: + bn.js "^4.1.0" + elliptic "^6.0.0" + +create-hash@^1.1.0, create-hash@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" + integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== + dependencies: + cipher-base "^1.0.1" + inherits "^2.0.1" + md5.js "^1.3.4" + ripemd160 "^2.0.1" + sha.js "^2.4.0" + +create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: + version "1.1.7" + resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" + integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== + dependencies: + cipher-base "^1.0.3" + create-hash "^1.1.0" + inherits "^2.0.1" + ripemd160 "^2.0.0" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +cross-spawn@^6.0.4: + version "6.0.5" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" + integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== + dependencies: + nice-try "^1.0.4" + path-key "^2.0.1" + semver "^5.5.0" + shebang-command "^1.2.0" + which "^1.2.9" + +crypto-browserify@^3.11.0: + version "3.12.0" + resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" + integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== + dependencies: + browserify-cipher "^1.0.0" + browserify-sign "^4.0.0" + create-ecdh "^4.0.0" + create-hash "^1.1.0" + create-hmac "^1.1.0" + diffie-hellman "^5.0.0" + inherits "^2.0.1" + pbkdf2 "^3.0.3" + public-encrypt "^4.0.0" + randombytes "^2.0.0" + randomfill "^1.0.3" + +css-color-names@0.0.4, css-color-names@^0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0" + integrity sha1-gIrcLnnPhHOAabZGyyDsJ762KeA= + +css-declaration-sorter@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz#c198940f63a76d7e36c1e71018b001721054cb22" + integrity sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA== + dependencies: + postcss "^7.0.1" + timsort "^0.3.0" + +css-modules-loader-core@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/css-modules-loader-core/-/css-modules-loader-core-1.1.0.tgz#5908668294a1becd261ae0a4ce21b0b551f21d16" + integrity sha1-WQhmgpShvs0mGuCkziGwtVHyHRY= + dependencies: + icss-replace-symbols "1.1.0" + postcss "6.0.1" + postcss-modules-extract-imports "1.1.0" + postcss-modules-local-by-default "1.2.0" + postcss-modules-scope "1.1.0" + postcss-modules-values "1.3.0" + +css-select-base-adapter@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz#3b2ff4972cc362ab88561507a95408a1432135d7" + integrity sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w== + +css-select@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-2.1.0.tgz#6a34653356635934a81baca68d0255432105dbef" + integrity sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ== + dependencies: + boolbase "^1.0.0" + css-what "^3.2.1" + domutils "^1.7.0" + nth-check "^1.0.2" + +css-selector-tokenizer@^0.7.0: + version "0.7.1" + resolved "https://registry.yarnpkg.com/css-selector-tokenizer/-/css-selector-tokenizer-0.7.1.tgz#a177271a8bca5019172f4f891fc6eed9cbf68d5d" + integrity sha512-xYL0AMZJ4gFzJQsHUKa5jiWWi2vH77WVNg7JYRyewwj6oPh4yb/y6Y9ZCw9dsj/9UauMhtuxR+ogQd//EdEVNA== + dependencies: + cssesc "^0.1.0" + fastparse "^1.1.1" + regexpu-core "^1.0.0" + +css-tree@1.0.0-alpha.37: + version "1.0.0-alpha.37" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.37.tgz#98bebd62c4c1d9f960ec340cf9f7522e30709a22" + integrity sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg== + dependencies: + mdn-data "2.0.4" + source-map "^0.6.1" + +css-unit-converter@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/css-unit-converter/-/css-unit-converter-1.1.1.tgz#d9b9281adcfd8ced935bdbaba83786897f64e996" + integrity sha1-2bkoGtz9jO2TW9urqDeGiX9k6ZY= + +css-what@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.2.1.tgz#f4a8f12421064621b456755e34a03a2c22df5da1" + integrity sha512-WwOrosiQTvyms+Ti5ZC5vGEK0Vod3FTt1ca+payZqvKuGJF+dq7bG63DstxtN0dpm6FxY27a/zS3Wten+gEtGw== + +cssesc@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-0.1.0.tgz#c814903e45623371a0477b40109aaafbeeaddbb4" + integrity sha1-yBSQPkViM3GgR3tAEJqq++6t27Q= + +cssesc@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-2.0.0.tgz#3b13bd1bb1cb36e1bcb5a4dcd27f54c5dcb35703" + integrity sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg== + +cssesc@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" + integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== + +cssnano-preset-default@^4.0.7: + version "4.0.7" + resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-4.0.7.tgz#51ec662ccfca0f88b396dcd9679cdb931be17f76" + integrity sha512-x0YHHx2h6p0fCl1zY9L9roD7rnlltugGu7zXSKQx6k2rYw0Hi3IqxcoAGF7u9Q5w1nt7vK0ulxV8Lo+EvllGsA== + dependencies: + css-declaration-sorter "^4.0.1" + cssnano-util-raw-cache "^4.0.1" + postcss "^7.0.0" + postcss-calc "^7.0.1" + postcss-colormin "^4.0.3" + postcss-convert-values "^4.0.1" + postcss-discard-comments "^4.0.2" + postcss-discard-duplicates "^4.0.2" + postcss-discard-empty "^4.0.1" + postcss-discard-overridden "^4.0.1" + postcss-merge-longhand "^4.0.11" + postcss-merge-rules "^4.0.3" + postcss-minify-font-values "^4.0.2" + postcss-minify-gradients "^4.0.2" + postcss-minify-params "^4.0.2" + postcss-minify-selectors "^4.0.2" + postcss-normalize-charset "^4.0.1" + postcss-normalize-display-values "^4.0.2" + postcss-normalize-positions "^4.0.2" + postcss-normalize-repeat-style "^4.0.2" + postcss-normalize-string "^4.0.2" + postcss-normalize-timing-functions "^4.0.2" + postcss-normalize-unicode "^4.0.1" + postcss-normalize-url "^4.0.1" + postcss-normalize-whitespace "^4.0.2" + postcss-ordered-values "^4.1.2" + postcss-reduce-initial "^4.0.3" + postcss-reduce-transforms "^4.0.2" + postcss-svgo "^4.0.2" + postcss-unique-selectors "^4.0.1" + +cssnano-util-get-arguments@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz#ed3a08299f21d75741b20f3b81f194ed49cc150f" + integrity sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8= + +cssnano-util-get-match@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz#c0e4ca07f5386bb17ec5e52250b4f5961365156d" + integrity sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0= + +cssnano-util-raw-cache@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz#b26d5fd5f72a11dfe7a7846fb4c67260f96bf282" + integrity sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA== + dependencies: + postcss "^7.0.0" + +cssnano-util-same-parent@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz#574082fb2859d2db433855835d9a8456ea18bbf3" + integrity sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q== + +cssnano@^4.1.10: + version "4.1.10" + resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-4.1.10.tgz#0ac41f0b13d13d465487e111b778d42da631b8b2" + integrity sha512-5wny+F6H4/8RgNlaqab4ktc3e0/blKutmq8yNlBFXA//nSFFAqAngjNVRzUvCgYROULmZZUoosL/KSoZo5aUaQ== + dependencies: + cosmiconfig "^5.0.0" + cssnano-preset-default "^4.0.7" + is-resolvable "^1.0.0" + postcss "^7.0.0" + +csso@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/csso/-/csso-4.0.2.tgz#e5f81ab3a56b8eefb7f0092ce7279329f454de3d" + integrity sha512-kS7/oeNVXkHWxby5tHVxlhjizRCSv8QdU7hB2FpdAibDU8FjTAolhNjKNTiLzXtUrKT6HwClE81yXwEk1309wg== + dependencies: + css-tree "1.0.0-alpha.37" + +cssom@0.3.x, cssom@^0.3.4: + version "0.3.8" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" + integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== + +cssstyle@^1.1.1: + version "1.4.0" + resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-1.4.0.tgz#9d31328229d3c565c61e586b02041a28fccdccf1" + integrity sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA== + dependencies: + cssom "0.3.x" + +csstype@^2.2.0: + version "2.6.7" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.7.tgz#20b0024c20b6718f4eda3853a1f5a1cce7f5e4a5" + integrity sha512-9Mcn9sFbGBAdmimWb2gLVDtFJzeKtDGIr76TUqmjZrw9LFXBMSU70lcs+C0/7fyCd6iBDqmksUcCOUIkisPHsQ== + +d3-hierarchy@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/d3-hierarchy/-/d3-hierarchy-1.1.9.tgz#2f6bee24caaea43f8dc37545fa01628559647a83" + integrity sha512-j8tPxlqh1srJHAtxfvOUwKNYJkQuBFdM1+JAUfq6xqH5eAqf93L7oG1NVqDa4CpFZNvnNKtCYEUC8KY9yEn9lQ== + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= + dependencies: + assert-plus "^1.0.0" + +data-urls@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-1.1.0.tgz#15ee0582baa5e22bb59c77140da8f9c76963bbfe" + integrity sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ== + dependencies: + abab "^2.0.0" + whatwg-mimetype "^2.2.0" + whatwg-url "^7.0.0" + +deasync@^0.1.14: + version "0.1.16" + resolved "https://registry.yarnpkg.com/deasync/-/deasync-0.1.16.tgz#44195eb4330fc9fc487f31ec614cbbdd57633897" + integrity sha512-FNCjDwxGbhK+Ye8fmE3p2ahIjERhkbuwX+WVGZPtSbAh9LfE1Saa2p0l+f0t11sIlk9D8W+Bym+cDp6r5yghAQ== + dependencies: + bindings "^1.5.0" + node-addon-api "^1.7.1" + +debug@2.6.9, debug@^2.2.0, debug@^2.3.3: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@^3.0.0: + version "3.2.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== + dependencies: + ms "^2.1.1" + +debug@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" + integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== + dependencies: + ms "^2.1.1" + +decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + +decode-uri-component@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= + +decompress-response@^4.2.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-4.2.1.tgz#414023cc7a302da25ce2ec82d0d5238ccafd8986" + integrity sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw== + dependencies: + mimic-response "^2.0.0" + +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + +deep-is@~0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= + +define-properties@^1.1.2, define-properties@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" + integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== + dependencies: + object-keys "^1.0.12" + +define-property@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= + dependencies: + is-descriptor "^0.1.0" + +define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= + dependencies: + is-descriptor "^1.0.0" + +define-property@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== + dependencies: + is-descriptor "^1.0.2" + isobject "^3.0.1" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= + +des.js@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" + integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA== + dependencies: + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + +detect-libc@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= + +diffie-hellman@^5.0.0: + version "5.0.3" + resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" + integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== + dependencies: + bn.js "^4.1.0" + miller-rabin "^4.0.0" + randombytes "^2.0.0" + +dom-serializer@0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51" + integrity sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g== + dependencies: + domelementtype "^2.0.1" + entities "^2.0.0" + +domain-browser@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" + integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== + +domelementtype@1, domelementtype@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" + integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== + +domelementtype@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.1.tgz#1f8bdfe91f5a78063274e803b4bdcedf6e94f94d" + integrity sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ== + +domexception@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/domexception/-/domexception-1.0.1.tgz#937442644ca6a31261ef36e3ec677fe805582c90" + integrity sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug== + dependencies: + webidl-conversions "^4.0.2" + +domhandler@^2.3.0: + version "2.4.2" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803" + integrity sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA== + dependencies: + domelementtype "1" + +domutils@^1.5.1, domutils@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" + integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg== + dependencies: + dom-serializer "0" + domelementtype "1" + +dot-prop@^4.1.1: + version "4.2.0" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57" + integrity sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ== + dependencies: + is-obj "^1.0.0" + +dotenv-expand@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-5.1.0.tgz#3fbaf020bfd794884072ea26b1e9791d45a629f0" + integrity sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA== + +dotenv@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-7.0.0.tgz#a2be3cd52736673206e8a85fb5210eea29628e7c" + integrity sha512-M3NhsLbV1i6HuGzBUH8vXrtxOk+tWmzWKDMbAVSUp3Zsjm7ywFeuwrUXhmhQyRK1q5B5GGy7hcXPbj3bnfZg2g== + +duplexer2@~0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1" + integrity sha1-ixLauHjA1p4+eJEFFmKjL8a93ME= + dependencies: + readable-stream "^2.0.2" + +ecc-jsbn@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= + dependencies: + jsbn "~0.1.0" + safer-buffer "^2.1.0" + +editorconfig@^0.15.3: + version "0.15.3" + resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-0.15.3.tgz#bef84c4e75fb8dcb0ce5cee8efd51c15999befc5" + integrity sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g== + dependencies: + commander "^2.19.0" + lru-cache "^4.1.5" + semver "^5.6.0" + sigmund "^1.0.1" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= + +ejs@^2.6.1: + version "2.7.4" + resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.7.4.tgz#48661287573dcc53e366c7a1ae52c3a120eec9ba" + integrity sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA== + +electron-to-chromium@^1.3.306: + version "1.3.307" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.307.tgz#e9b98901371d20164af7c0ca5bc820bd4305ccd3" + integrity sha512-01rTsAqHwf3D2X6NtlUvzB2hxDj67kiTVIO5GWdFb2unA0QvFvrjyrtc993ByRLF+surlr+9AvJdD0UYs5HzwA== + +elliptic@^6.0.0: + version "6.5.1" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.1.tgz#c380f5f909bf1b9b4428d028cd18d3b0efd6b52b" + integrity sha512-xvJINNLbTeWQjrl6X+7eQCrIy/YPv5XCpKW6kB5mKvtnGILoLDcySuwomfdzt0BMdLNVnuRNTuzKNHj0bva1Cg== + dependencies: + bn.js "^4.4.0" + brorand "^1.0.1" + hash.js "^1.0.0" + hmac-drbg "^1.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.0" + +emoji-regex@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== + +emojis-list@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" + integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k= + +emphasize@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/emphasize/-/emphasize-2.1.0.tgz#4dbb279f3df30822e8d9c6476b856f09706a0dd8" + integrity sha512-wRlO0Qulw2jieQynsS3STzTabIhHCyjTjZraSkchOiT8rdvWZlahJAJ69HRxwGkv2NThmci2MSnDfJ60jB39tw== + dependencies: + chalk "^2.4.0" + highlight.js "~9.12.0" + lowlight "~1.9.0" + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= + +end-of-stream@^1.1.0, end-of-stream@^1.4.1: + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + +entities@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" + integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== + +entities@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4" + integrity sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw== + +error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +es-abstract@^1.12.0, es-abstract@^1.5.1: + version "1.16.0" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.16.0.tgz#d3a26dc9c3283ac9750dca569586e976d9dcc06d" + integrity sha512-xdQnfykZ9JMEiasTAJZJdMWCQ1Vm00NBw79/AWi7ELfZuuPCSOMDZbT9mkOfSctVtfhb+sAAzrm+j//GjjLHLg== + dependencies: + es-to-primitive "^1.2.0" + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.0" + is-callable "^1.1.4" + is-regex "^1.0.4" + object-inspect "^1.6.0" + object-keys "^1.1.1" + string.prototype.trimleft "^2.1.0" + string.prototype.trimright "^2.1.0" + +es-to-primitive@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= + +escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + +escodegen@^1.11.0, escodegen@^1.11.1: + version "1.12.0" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.12.0.tgz#f763daf840af172bb3a2b6dd7219c0e17f7ff541" + integrity sha512-TuA+EhsanGcme5T3R0L80u4t8CpbXQjegRmf7+FPTJrtCTErXFeelblRgHQa1FofEzqYYJmJ/OqjTwREp9qgmg== + dependencies: + esprima "^3.1.3" + estraverse "^4.2.0" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.6.1" + +escodegen@~1.9.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.9.1.tgz#dbae17ef96c8e4bedb1356f4504fa4cc2f7cb7e2" + integrity sha512-6hTjO1NAWkHnDk3OqQ4YrCuwwmGHL9S3nPlzBOUG/R44rda3wLNrfvQ5fkSGjyhHFKM7ALPKcKGrwvCLe0lC7Q== + dependencies: + esprima "^3.1.3" + estraverse "^4.2.0" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.6.1" + +esprima@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" + integrity sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM= + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +estraverse@^4.2.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +esutils@^2.0.0, esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +eventemitter3@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.0.tgz#d65176163887ee59f386d64c82610b696a4a74eb" + integrity sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg== + +events@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.0.0.tgz#9a0a0dfaf62893d92b875b8f2698ca4114973e88" + integrity sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA== + +evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" + integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== + dependencies: + md5.js "^1.3.4" + safe-buffer "^5.1.1" + +expand-brackets@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= + dependencies: + debug "^2.3.3" + define-property "^0.2.5" + extend-shallow "^2.0.1" + posix-character-classes "^0.1.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +expand-template@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c" + integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg== + +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= + dependencies: + is-extendable "^0.1.0" + +extend-shallow@^3.0.0, extend-shallow@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= + dependencies: + assign-symbols "^1.0.0" + is-extendable "^1.0.1" + +extend@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + +extglob@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== + dependencies: + array-unique "^0.3.2" + define-property "^1.0.0" + expand-brackets "^2.1.4" + extend-shallow "^2.0.1" + fragment-cache "^0.2.1" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= + +extsprintf@^1.2.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" + integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= + +falafel@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/falafel/-/falafel-2.1.0.tgz#96bb17761daba94f46d001738b3cedf3a67fe06c" + integrity sha1-lrsXdh2rqU9G0AFzizzt86Z/4Gw= + dependencies: + acorn "^5.0.0" + foreach "^2.0.5" + isarray "0.0.1" + object-keys "^1.0.6" + +fast-deep-equal@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" + integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= + +fast-glob@^3.0.4: + version "3.1.0" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.1.0.tgz#77375a7e3e6f6fc9b18f061cddd28b8d1eec75ae" + integrity sha512-TrUz3THiq2Vy3bjfQUB2wNyPdGBeGmdjbzzBLhfHN4YFurYptCKwGq/TfiRavbGywFRzY6U2CdmQ1zmsY5yYaw== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.0" + merge2 "^1.3.0" + micromatch "^4.0.2" + +fast-json-stable-stringify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" + integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= + +fast-levenshtein@~2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= + +fastparse@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.2.tgz#91728c5a5942eced8531283c79441ee4122c35a9" + integrity sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ== + +fastq@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.6.0.tgz#4ec8a38f4ac25f21492673adb7eae9cfef47d1c2" + integrity sha512-jmxqQ3Z/nXoeyDmWAzF9kH1aGZSis6e/SbfPmJpUnyZ0ogr6iscHQaml4wsEepEWSdtmpy+eVXmCRIMpxaXqOA== + dependencies: + reusify "^1.0.0" + +fault@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/fault/-/fault-1.0.3.tgz#4da88cf979b6b792b4e13c7ec836767725170b7e" + integrity sha512-sfFuP4X0hzrbGKjAUNXYvNqsZ5F6ohx/dZ9I0KQud/aiZNwg263r5L9yGB0clvXHCkzXh5W3t7RSHchggYIFmA== + dependencies: + format "^0.2.2" + +file-uri-to-path@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" + integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== + +filesize@^3.6.0: + version "3.6.1" + resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.6.1.tgz#090bb3ee01b6f801a8a8be99d31710b3422bb317" + integrity sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg== + +fill-range@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= + dependencies: + extend-shallow "^2.0.1" + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range "^2.1.0" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +finalhandler@1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" + integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "~2.3.0" + parseurl "~1.3.3" + statuses "~1.5.0" + unpipe "~1.0.0" + +find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== + dependencies: + locate-path "^3.0.0" + +follow-redirects@^1.0.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.9.0.tgz#8d5bcdc65b7108fe1508649c79c12d732dcedb4f" + integrity sha512-CRcPzsSIbXyVDl0QI01muNDu69S8trU4jArW9LpOt2WtC6LyUJetcIrmfHsRBx7/Jb6GHJUiuqyYxPooFfNt6A== + dependencies: + debug "^3.0.0" + +for-in@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= + +foreach@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" + integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k= + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= + +form-data@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" + integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + +format@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/format/-/format-0.2.2.tgz#d6170107e9efdc4ed30c9dc39016df942b5cb58b" + integrity sha1-1hcBB+nv3E7TDJ3DkBbflCtctYs= + +fragment-cache@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= + dependencies: + map-cache "^0.2.2" + +fs-constants@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" + integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +gauge@~2.7.3: + version "2.7.4" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= + dependencies: + aproba "^1.0.3" + console-control-strings "^1.0.0" + has-unicode "^2.0.0" + object-assign "^4.1.0" + signal-exit "^3.0.0" + string-width "^1.0.1" + strip-ansi "^3.0.1" + wide-align "^1.1.0" + +generic-names@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/generic-names/-/generic-names-1.0.3.tgz#2d786a121aee508876796939e8e3bff836c20917" + integrity sha1-LXhqEhruUIh2eWk56OO/+DbCCRc= + dependencies: + loader-utils "^0.2.16" + +get-caller-file@^2.0.1: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-port@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/get-port/-/get-port-4.2.0.tgz#e37368b1e863b7629c43c5a323625f95cf24b119" + integrity sha512-/b3jarXkH8KJoOMQc3uVGHASwGLPq3gSFJ7tgJm2diza+bydJPTGOibin2steecKeOylE8oY2JERlVWkAJO6yw== + +get-value@^2.0.3, get-value@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= + dependencies: + assert-plus "^1.0.0" + +github-from-package@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" + integrity sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4= + +glob-parent@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.0.tgz#5f4c1d1e748d30cd73ad2944b3577a81b081e8c2" + integrity sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw== + dependencies: + is-glob "^4.0.1" + +glob@^7.1.3, glob@^7.1.4: + version "7.1.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" + integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +grapheme-breaker@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/grapheme-breaker/-/grapheme-breaker-0.3.2.tgz#5b9e6b78c3832452d2ba2bb1cb830f96276410ac" + integrity sha1-W55reMODJFLSuiuxy4MPlidkEKw= + dependencies: + brfs "^1.2.0" + unicode-trie "^0.3.1" + +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= + +har-validator@~5.1.0: + version "5.1.3" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080" + integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g== + dependencies: + ajv "^6.5.5" + har-schema "^2.0.0" + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= + dependencies: + ansi-regex "^2.0.0" + +has-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" + integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo= + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + +has-symbols@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" + integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== + +has-unicode@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= + +has-value@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= + dependencies: + get-value "^2.0.3" + has-values "^0.1.4" + isobject "^2.0.0" + +has-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= + dependencies: + get-value "^2.0.6" + has-values "^1.0.0" + isobject "^3.0.0" + +has-values@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= + +has-values@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + +has@^1.0.0, has@^1.0.1, has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +hash-base@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918" + integrity sha1-X8hoaEfs1zSZQDMZprCj8/auSRg= + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +hash.js@^1.0.0, hash.js@^1.0.3: + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + +hex-color-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e" + integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ== + +highlight.js@~9.12.0: + version "9.12.0" + resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.12.0.tgz#e6d9dbe57cbefe60751f02af336195870c90c01e" + integrity sha1-5tnb5Xy+/mB1HwKvM2GVhwyQwB4= + +hmac-drbg@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + +hsl-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/hsl-regex/-/hsl-regex-1.0.0.tgz#d49330c789ed819e276a4c0d272dffa30b18fe6e" + integrity sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4= + +hsla-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/hsla-regex/-/hsla-regex-1.0.0.tgz#c1ce7a3168c8c6614033a4b5f7877f3b225f9c38" + integrity sha1-wc56MWjIxmFAM6S194d/OyJfnDg= + +html-comment-regex@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.2.tgz#97d4688aeb5c81886a364faa0cad1dda14d433a7" + integrity sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ== + +html-encoding-sniffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz#e70d84b94da53aa375e11fe3a351be6642ca46f8" + integrity sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw== + dependencies: + whatwg-encoding "^1.0.1" + +html-tags@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-1.2.0.tgz#c78de65b5663aa597989dd2b7ab49200d7e4db98" + integrity sha1-x43mW1Zjqll5id0rerSSANfk25g= + +htmlnano@^0.2.2: + version "0.2.5" + resolved "https://registry.yarnpkg.com/htmlnano/-/htmlnano-0.2.5.tgz#134fd9548c7cbe51c8508ce434a3f9488cff1b0b" + integrity sha512-X1iPSwXG/iF9bVs+/obt2n6F64uH0ETkA8zp7qFDmLW9/+A6ueHGeb/+qD67T21qUY22owZPMdawljN50ajkqA== + dependencies: + cssnano "^4.1.10" + normalize-html-whitespace "^1.0.0" + posthtml "^0.12.0" + posthtml-render "^1.1.5" + purgecss "^1.4.0" + svgo "^1.3.2" + terser "^4.3.9" + uncss "^0.17.2" + +htmlparser2@^3.9.2: + version "3.10.1" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f" + integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ== + dependencies: + domelementtype "^1.3.1" + domhandler "^2.3.0" + domutils "^1.5.1" + entities "^1.1.1" + inherits "^2.0.1" + readable-stream "^3.1.1" + +http-proxy-middleware@^0.19.1: + version "0.19.1" + resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz#183c7dc4aa1479150306498c210cdaf96080a43a" + integrity sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q== + dependencies: + http-proxy "^1.17.0" + is-glob "^4.0.0" + lodash "^4.17.11" + micromatch "^3.1.10" + +http-proxy@^1.17.0: + version "1.18.0" + resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.0.tgz#dbe55f63e75a347db7f3d99974f2692a314a6a3a" + integrity sha512-84I2iJM/n1d4Hdgc6y2+qY5mDaz2PUVjlg9znE9byl+q0uC3DeByqBGReQu5tpLK0TAqTIXScRUV+dg7+bUPpQ== + dependencies: + eventemitter3 "^4.0.0" + follow-redirects "^1.0.0" + requires-port "^1.0.0" + +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +https-browserify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" + integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= + +iconv-lite@0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +icss-replace-symbols@1.1.0, icss-replace-symbols@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded" + integrity sha1-Bupvg2ead0njhs/h/oEq5dsiPe0= + +ieee754@^1.1.4: + version "1.1.13" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" + integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg== + +import-fresh@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" + integrity sha1-2BNVwVYS04bGH53dOSLUMEgipUY= + dependencies: + caller-path "^2.0.0" + resolve-from "^3.0.0" + +indexes-of@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" + integrity sha1-8w9xbI4r00bHtn0985FVZqfAVgc= + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +inherits@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" + integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= + +inherits@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= + +ini@^1.3.4, ini@~1.3.0: + version "1.3.5" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" + integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== + +ink-spinner@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ink-spinner/-/ink-spinner-3.0.1.tgz#7b4b206d2b18538701fd92593f9acabbfe308dce" + integrity sha512-AVR4Z/NXDQ7dT5ltWcCzFS9Dd4T8eaO//E2UO8VYNiJcZpPCSJ11o5A0UVPcMlZxGbGD6ikUFDR3ZgPUQk5haQ== + dependencies: + cli-spinners "^1.0.0" + prop-types "^15.5.10" + +ink@^2.1.1: + version "2.5.0" + resolved "https://registry.yarnpkg.com/ink/-/ink-2.5.0.tgz#66cf988b65ca06d14f00f385eb531fde29f95819" + integrity sha512-HUkVglJ11cXK+W1a5cKNoOCxLkDi5hbDMAWSFDcwF2kpNd0eoX+2/cpaTP9BTFaQ8RJk7O59NxKMmyPXkmxo7w== + dependencies: + "@types/react" "^16.8.6" + ansi-escapes "^4.2.1" + arrify "^1.0.1" + auto-bind "^2.0.0" + chalk "^2.4.1" + cli-cursor "^2.1.0" + cli-truncate "^1.1.0" + is-ci "^2.0.0" + lodash.throttle "^4.1.1" + log-update "^3.0.0" + prop-types "^15.6.2" + react-reconciler "^0.21.0" + scheduler "^0.15.0" + signal-exit "^3.0.2" + slice-ansi "^1.0.0" + string-length "^2.0.0" + widest-line "^2.0.0" + wrap-ansi "^5.0.0" + yoga-layout-prebuilt "^1.9.3" + +invariant@^2.2.2: + version "2.2.4" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== + dependencies: + loose-envify "^1.0.0" + +is-absolute-url@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6" + integrity sha1-UFMN+4T8yap9vnhS6Do3uTufKqY= + +is-absolute-url@^3.0.1: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-3.0.3.tgz#96c6a22b6a23929b11ea0afb1836c36ad4a5d698" + integrity sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q== + +is-accessor-descriptor@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= + dependencies: + kind-of "^3.0.2" + +is-accessor-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== + dependencies: + kind-of "^6.0.0" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= + +is-arrayish@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" + integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== + +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + +is-callable@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" + integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== + +is-ci@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" + integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== + dependencies: + ci-info "^2.0.0" + +is-color-stop@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-color-stop/-/is-color-stop-1.1.0.tgz#cfff471aee4dd5c9e158598fbe12967b5cdad345" + integrity sha1-z/9HGu5N1cnhWFmPvhKWe1za00U= + dependencies: + css-color-names "^0.0.4" + hex-color-regex "^1.1.0" + hsl-regex "^1.0.0" + hsla-regex "^1.0.0" + rgb-regex "^1.0.1" + rgba-regex "^1.0.0" + +is-data-descriptor@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= + dependencies: + kind-of "^3.0.2" + +is-data-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== + dependencies: + kind-of "^6.0.0" + +is-date-object@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" + integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY= + +is-descriptor@^0.1.0: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== + dependencies: + is-accessor-descriptor "^0.1.6" + is-data-descriptor "^0.1.4" + kind-of "^5.0.0" + +is-descriptor@^1.0.0, is-descriptor@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== + dependencies: + is-accessor-descriptor "^1.0.0" + is-data-descriptor "^1.0.0" + kind-of "^6.0.2" + +is-directory@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" + integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= + +is-extendable@^0.1.0, is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= + +is-extendable@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== + dependencies: + is-plain-object "^2.0.4" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + +is-glob@^4.0.0, is-glob@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" + integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== + dependencies: + is-extglob "^2.1.1" + +is-html@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-html/-/is-html-1.1.0.tgz#e04f1c18d39485111396f9a0273eab51af218464" + integrity sha1-4E8cGNOUhRETlvmgJz6rUa8hhGQ= + dependencies: + html-tags "^1.0.0" + +is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= + dependencies: + kind-of "^3.0.2" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-obj@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" + integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= + +is-plain-object@^2.0.3, is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +is-regex@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" + integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= + dependencies: + has "^1.0.1" + +is-resolvable@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" + integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== + +is-svg@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-3.0.0.tgz#9321dbd29c212e5ca99c4fa9794c714bcafa2f75" + integrity sha512-gi4iHK53LR2ujhLVVj+37Ykh9GLqYHX6JOVXbLAucaG/Cqw9xwdFOjDM2qeifLs1sF1npXXFvDu0r5HNgCMrzQ== + dependencies: + html-comment-regex "^1.1.0" + +is-symbol@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38" + integrity sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw== + dependencies: + has-symbols "^1.0.0" + +is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= + +is-url@^1.2.2: + version "1.2.4" + resolved "https://registry.yarnpkg.com/is-url/-/is-url-1.2.4.tgz#04a4df46d28c4cff3d73d01ff06abeb318a1aa52" + integrity sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww== + +is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= + +isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + +isbinaryfile@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-4.0.2.tgz#bfc45642da645681c610cca831022e30af426488" + integrity sha512-C3FSxJdNrEr2F4z6uFtNzECDM5hXk+46fxaa+cwBe5/XrWSmzdG8DDgyjfX6/NRdBB21q2JXuRAzPCUs+fclnQ== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= + dependencies: + isarray "1.0.0" + +isobject@^3.0.0, isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= + +js-beautify@^1.8.9: + version "1.10.2" + resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.10.2.tgz#88c9099cd6559402b124cfab18754936f8a7b178" + integrity sha512-ZtBYyNUYJIsBWERnQP0rPN9KjkrDfJcMjuVGcvXOUJrD1zmOGwhRwQ4msG+HJ+Ni/FA7+sRQEMYVzdTQDvnzvQ== + dependencies: + config-chain "^1.1.12" + editorconfig "^0.15.3" + glob "^7.1.3" + mkdirp "~0.5.1" + nopt "~4.0.1" + +js-levenshtein@^1.1.3, js-levenshtein@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d" + integrity sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g== + +"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^3.13.1: + version "3.13.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" + integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= + +jsdom@^14.1.0: + version "14.1.0" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-14.1.0.tgz#916463b6094956b0a6c1782c94e380cd30e1981b" + integrity sha512-O901mfJSuTdwU2w3Sn+74T+RnDVP+FuV5fH8tcPWyqrseRAb0s5xOtPgCFiPOtLcyK7CLIJwPyD83ZqQWvA5ng== + dependencies: + abab "^2.0.0" + acorn "^6.0.4" + acorn-globals "^4.3.0" + array-equal "^1.0.0" + cssom "^0.3.4" + cssstyle "^1.1.1" + data-urls "^1.1.0" + domexception "^1.0.1" + escodegen "^1.11.0" + html-encoding-sniffer "^1.0.2" + nwsapi "^2.1.3" + parse5 "5.1.0" + pn "^1.1.0" + request "^2.88.0" + request-promise-native "^1.0.5" + saxes "^3.1.9" + symbol-tree "^3.2.2" + tough-cookie "^2.5.0" + w3c-hr-time "^1.0.1" + w3c-xmlserializer "^1.1.2" + webidl-conversions "^4.0.2" + whatwg-encoding "^1.0.5" + whatwg-mimetype "^2.3.0" + whatwg-url "^7.0.0" + ws "^6.1.2" + xml-name-validator "^3.0.0" + +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== + +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= + +json-parse-better-errors@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" + integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema@0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= + +json-source-map@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/json-source-map/-/json-source-map-0.6.1.tgz#e0b1f6f4ce13a9ad57e2ae165a24d06e62c79a0f" + integrity sha512-1QoztHPsMQqhDq0hlXY5ZqcEdUzxQEIxgFkKl4WUp2pgShObl+9ovi4kRh2TfvAfxAoHOJ9vIMEqk3k4iex7tg== + +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= + +json5@^0.5.0: + version "0.5.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" + integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE= + +json5@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" + integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== + dependencies: + minimist "^1.2.0" + +json5@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.1.tgz#81b6cb04e9ba496f1c7005d07b4368a2638f90b6" + integrity sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ== + dependencies: + minimist "^1.2.0" + +jsprim@^1.2.2: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" + integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.2.3" + verror "1.10.0" + +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= + dependencies: + is-buffer "^1.1.5" + +kind-of@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= + dependencies: + is-buffer "^1.1.5" + +kind-of@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== + +kind-of@^6.0.0, kind-of@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" + integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== + +levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + +loader-utils@^0.2.16: + version "0.2.17" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.17.tgz#f86e6374d43205a6e6c60e9196f17c0299bfb348" + integrity sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g= + dependencies: + big.js "^3.1.3" + emojis-list "^2.0.0" + json5 "^0.5.0" + object-assign "^4.0.1" + +locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== + dependencies: + p-locate "^3.0.0" + path-exists "^3.0.0" + +lodash.camelcase@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" + integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY= + +lodash.clone@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.clone/-/lodash.clone-4.5.0.tgz#195870450f5a13192478df4bc3d23d2dea1907b6" + integrity sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y= + +lodash.clonedeep@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" + integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= + +lodash.memoize@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" + integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= + +lodash.sortby@^4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" + integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= + +lodash.throttle@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" + integrity sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ= + +lodash.uniq@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" + integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= + +lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.15, lodash@^4.17.4: + version "4.17.15" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" + integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== + +log-update@^3.0.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/log-update/-/log-update-3.3.0.tgz#3b0501815123f66cb33f300e3dac2a2b6ad3fdf5" + integrity sha512-YSKm5n+YjZoGZT5lfmOqasVH1fIH9xQA9A81Y48nZ99PxAP62vdCCtua+Gcu6oTn0nqtZd/LwRV+Vflo53ZDWA== + dependencies: + ansi-escapes "^3.2.0" + cli-cursor "^2.1.0" + wrap-ansi "^5.0.0" + +loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +lowlight@~1.9.0: + version "1.9.2" + resolved "https://registry.yarnpkg.com/lowlight/-/lowlight-1.9.2.tgz#0b9127e3cec2c3021b7795dd81005c709a42fdd1" + integrity sha512-Ek18ElVCf/wF/jEm1b92gTnigh94CtBNWiZ2ad+vTgW7cTmQxUY3I98BjHK68gZAJEWmybGBZgx9qv3QxLQB/Q== + dependencies: + fault "^1.0.2" + highlight.js "~9.12.0" + +lru-cache@^4.1.5: + version "4.1.5" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" + integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== + dependencies: + pseudomap "^1.0.2" + yallist "^2.1.2" + +magic-string@^0.22.4: + version "0.22.5" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.22.5.tgz#8e9cf5afddf44385c1da5bc2a6a0dbd10b03657e" + integrity sha512-oreip9rJZkzvA8Qzk9HFs8fZGF/u7H/gtrE8EN6RjKJ9kh2HlC+yQ2QezifqTZfGyiuAV0dRv5a+y/8gBb1m9w== + dependencies: + vlq "^0.2.2" + +map-cache@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= + +map-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= + dependencies: + object-visit "^1.0.0" + +md5.js@^1.3.4: + version "1.3.5" + resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" + integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +mdn-data@2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b" + integrity sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA== + +memoize-one@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.1.1.tgz#047b6e3199b508eaec03504de71229b8eb1d75c0" + integrity sha512-HKeeBpWvqiVJD57ZUAsJNm71eHTykffzcLZVYWiVfQeI1rJtuEaS7hQiEpWfVVk18donPwJEcFKIkCmPJNOhHA== + +merge-source-map@1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/merge-source-map/-/merge-source-map-1.0.4.tgz#a5de46538dae84d4114cc5ea02b4772a6346701f" + integrity sha1-pd5GU42uhNQRTMXqArR3KmNGcB8= + dependencies: + source-map "^0.5.6" + +merge2@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.3.0.tgz#5b366ee83b2f1582c48f87e47cf1a9352103ca81" + integrity sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw== + +micromatch@^3.0.4, micromatch@^3.1.10: + version "3.1.10" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + braces "^2.3.1" + define-property "^2.0.2" + extend-shallow "^3.0.2" + extglob "^2.0.4" + fragment-cache "^0.2.1" + kind-of "^6.0.2" + nanomatch "^1.2.9" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.2" + +micromatch@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259" + integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q== + dependencies: + braces "^3.0.1" + picomatch "^2.0.5" + +miller-rabin@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" + integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== + dependencies: + bn.js "^4.0.0" + brorand "^1.0.1" + +mime-db@1.42.0: + version "1.42.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.42.0.tgz#3e252907b4c7adb906597b4b65636272cf9e7bac" + integrity sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ== + +mime-types@^2.1.12, mime-types@~2.1.19: + version "2.1.25" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.25.tgz#39772d46621f93e2a80a856c53b86a62156a6437" + integrity sha512-5KhStqB5xpTAeGqKBAMgwaYMnQik7teQN4IAzC7npDv6kzeU6prfkR67bc87J1kWMPGkoaZSq1npmexMgkmEVg== + dependencies: + mime-db "1.42.0" + +mime@^2.4.4: + version "2.4.4" + resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.4.tgz#bd7b91135fc6b01cde3e9bae33d659b63d8857e5" + integrity sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA== + +mimic-fn@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" + integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== + +mimic-response@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.0.0.tgz#996a51c60adf12cb8a87d7fb8ef24c2f3d5ebb46" + integrity sha512-8ilDoEapqA4uQ3TwS0jakGONKXVJqpy+RpM+3b7pLdOjghCrEiGp9SRkFbUHAmZW9vdnrENWHjaweIoTIJExSQ== + +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= + +minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= + +minimist@^1.1.3, minimist@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= + +mixin-deep@^1.2.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" + integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== + dependencies: + for-in "^1.0.2" + is-extendable "^1.0.1" + +mkdirp@^0.5.1, mkdirp@~0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= + dependencies: + minimist "0.0.8" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + +ms@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +nanomatch@^1.2.9: + version "1.2.13" + resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + define-property "^2.0.2" + extend-shallow "^3.0.2" + fragment-cache "^0.2.1" + is-windows "^1.0.2" + kind-of "^6.0.2" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +napi-build-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.1.tgz#1381a0f92c39d66bf19852e7873432fc2123e508" + integrity sha512-boQj1WFgQH3v4clhu3mTNfP+vOBxorDlE8EKiMjUlLG3C4qAESnn9AxIOkFgTR2c9LtzNjPrjS60cT27ZKBhaA== + +ncp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ncp/-/ncp-2.0.0.tgz#195a21d6c46e361d2fb1281ba38b91e9df7bdbb3" + integrity sha1-GVoh1sRuNh0vsSgbo4uR6d9727M= + +nice-try@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" + integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== + +node-abi@^2.7.0: + version "2.12.0" + resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.12.0.tgz#40e9cfabdda1837863fa825e7dfa0b15686adf6f" + integrity sha512-VhPBXCIcvmo/5K8HPmnWJyyhvgKxnHTUMXR/XwGHV68+wrgkzST4UmQrY/XszSWA5dtnXpNp528zkcyJ/pzVcw== + dependencies: + semver "^5.4.1" + +node-addon-api@^1.6.2, node-addon-api@^1.7.1: + version "1.7.1" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-1.7.1.tgz#cf813cd69bb8d9100f6bdca6755fc268f54ac492" + integrity sha512-2+DuKodWvwRTrCfKOeR24KIc5unKjOh8mz17NCzVnHWfjAdDqbfbjqh7gUT+BkXBRQM52+xCHciKWonJ3CbJMQ== + +node-forge@^0.8.1: + version "0.8.5" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.8.5.tgz#57906f07614dc72762c84cef442f427c0e1b86ee" + integrity sha512-vFMQIWt+J/7FLNyKouZ9TazT74PRV3wgv9UT4cRjC8BffxFbKXkgIWR42URCPSnHm/QDz6BOlb2Q0U4+VQT67Q== + +node-libs-browser@^2.0.0, node-libs-browser@^2.1.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" + integrity sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q== + dependencies: + assert "^1.1.1" + browserify-zlib "^0.2.0" + buffer "^4.3.0" + console-browserify "^1.1.0" + constants-browserify "^1.0.0" + crypto-browserify "^3.11.0" + domain-browser "^1.1.1" + events "^3.0.0" + https-browserify "^1.0.0" + os-browserify "^0.3.0" + path-browserify "0.0.1" + process "^0.11.10" + punycode "^1.2.4" + querystring-es3 "^0.2.0" + readable-stream "^2.3.3" + stream-browserify "^2.0.1" + stream-http "^2.7.2" + string_decoder "^1.0.0" + timers-browserify "^2.0.4" + tty-browserify "0.0.0" + url "^0.11.0" + util "^0.11.0" + vm-browserify "^1.0.1" + +node-modules-regexp@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz#8d9dbe28964a4ac5712e9131642107c71e90ec40" + integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA= + +node-releases@^1.1.40: + version "1.1.40" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.40.tgz#a94facfa8e2d612302601ca1361741d529c4515a" + integrity sha512-r4LPcC5b/bS8BdtWH1fbeK88ib/wg9aqmg6/s3ngNLn2Ewkn/8J6Iw3P9RTlfIAdSdvYvQl2thCY5Y+qTAQ2iQ== + dependencies: + semver "^6.3.0" + +noop-logger@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/noop-logger/-/noop-logger-0.1.1.tgz#94a2b1633c4f1317553007d8966fd0e841b6a4c2" + integrity sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI= + +nopt@~4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" + integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00= + dependencies: + abbrev "1" + osenv "^0.1.4" + +normalize-html-whitespace@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/normalize-html-whitespace/-/normalize-html-whitespace-1.0.0.tgz#5e3c8e192f1b06c3b9eee4b7e7f28854c7601e34" + integrity sha512-9ui7CGtOOlehQu0t/OhhlmDyc71mKVlv+4vF+me4iZLPrNtRL2xoquEdfZxasC/bdQi/Hr3iTrpyRKIG+ocabA== + +normalize-url@^3.0.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559" + integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg== + +npmlog@^4.0.1: + version "4.1.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" + integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== + dependencies: + are-we-there-yet "~1.1.2" + console-control-strings "~1.1.0" + gauge "~2.7.3" + set-blocking "~2.0.0" + +nth-check@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" + integrity sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg== + dependencies: + boolbase "~1.0.0" + +nullthrows@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/nullthrows/-/nullthrows-1.1.1.tgz#7818258843856ae971eae4208ad7d7eb19a431b1" + integrity sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw== + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= + +nwsapi@^2.1.3: + version "2.2.0" + resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7" + integrity sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ== + +oauth-sign@~0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" + integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== + +object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= + +object-copy@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= + dependencies: + copy-descriptor "^0.1.0" + define-property "^0.2.5" + kind-of "^3.0.3" + +object-inspect@^1.6.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67" + integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw== + +object-inspect@~1.4.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.4.1.tgz#37ffb10e71adaf3748d05f713b4c9452f402cbc4" + integrity sha512-wqdhLpfCUbEsoEwl3FXwGyv8ief1k/1aUdIPCqVnupM6e8l63BEJdiF/0swtn04/8p05tG/T0FrpTlfwvljOdw== + +object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.0.6, object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object-visit@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= + dependencies: + isobject "^3.0.0" + +object.assign@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" + integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== + dependencies: + define-properties "^1.1.2" + function-bind "^1.1.1" + has-symbols "^1.0.0" + object-keys "^1.0.11" + +object.getownpropertydescriptors@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" + integrity sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY= + dependencies: + define-properties "^1.1.2" + es-abstract "^1.5.1" + +object.pick@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= + dependencies: + isobject "^3.0.1" + +object.values@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.0.tgz#bf6810ef5da3e5325790eaaa2be213ea84624da9" + integrity sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.12.0" + function-bind "^1.1.1" + has "^1.0.3" + +on-finished@~2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= + dependencies: + ee-first "1.1.1" + +once@^1.3.0, once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +onetime@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" + integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ= + dependencies: + mimic-fn "^1.0.0" + +optionator@^0.8.1: + version "0.8.3" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" + integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.6" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + word-wrap "~1.2.3" + +os-browserify@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" + integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= + +os-homedir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= + +os-tmpdir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= + +osenv@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" + integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.0" + +p-limit@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537" + integrity sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg== + dependencies: + p-try "^2.0.0" + +p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== + dependencies: + p-limit "^2.0.0" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +pako@^0.2.5: + version "0.2.9" + resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75" + integrity sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU= + +pako@~1.0.5: + version "1.0.10" + resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.10.tgz#4328badb5086a426aa90f541977d4955da5c9732" + integrity sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw== + +parcel@2.0.0-alpha.3.2: + version "2.0.0-alpha.3.2" + resolved "https://registry.yarnpkg.com/parcel/-/parcel-2.0.0-alpha.3.2.tgz#d59de34f491608197d4f9e40688545d62aada08e" + integrity sha512-FG8JZtY2MAhxYANtLUlRbPNhTqtDB6zDQ+GVPBgzs6xlzyWSEdzayJ2a25Nnee+SBptV9nSHavkMrtP3YLrnAg== + dependencies: + "@parcel/config-default" "^2.0.0-alpha.3.1" + "@parcel/core" "^2.0.0-alpha.3.2" + "@parcel/fs" "^2.0.0-alpha.3.1" + "@parcel/logger" "^2.0.0-alpha.3.1" + "@parcel/package-manager" "^2.0.0-alpha.3.1" + chalk "^2.1.0" + commander "^2.19.0" + get-port "^4.2.0" + react "^16.7.0" + v8-compile-cache "^2.0.0" + +parse-asn1@^5.0.0: + version "5.1.5" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.5.tgz#003271343da58dc94cace494faef3d2147ecea0e" + integrity sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ== + dependencies: + asn1.js "^4.0.0" + browserify-aes "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.0" + pbkdf2 "^3.0.3" + safe-buffer "^5.1.1" + +parse-json@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" + integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= + dependencies: + error-ex "^1.3.1" + json-parse-better-errors "^1.0.1" + +parse-ms@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/parse-ms/-/parse-ms-2.1.0.tgz#348565a753d4391fa524029956b172cb7753097d" + integrity sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA== + +parse5@5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.0.tgz#c59341c9723f414c452975564c7c00a68d58acd2" + integrity sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ== + +parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + +pascalcase@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= + +path-browserify@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" + integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ== + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +path-key@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= + +path-parse@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" + integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== + +pbkdf2@^3.0.3: + version "3.0.17" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.17.tgz#976c206530617b14ebb32114239f7b09336e93a6" + integrity sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA== + dependencies: + create-hash "^1.1.2" + create-hmac "^1.1.4" + ripemd160 "^2.0.1" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= + +physical-cpu-count@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/physical-cpu-count/-/physical-cpu-count-2.0.0.tgz#18de2f97e4bf7a9551ad7511942b5496f7aba660" + integrity sha1-GN4vl+S/epVRrXURlCtUlverpmA= + +picomatch@^2.0.5: + version "2.1.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.1.1.tgz#ecdfbea7704adb5fe6fb47f9866c4c0e15e905c5" + integrity sha512-OYMyqkKzK7blWO/+XZYP6w8hH0LDvkBvdvKukti+7kqYFCiEAk+gI3DWnryapc0Dau05ugGTy0foQ6mqn4AHYA== + +pirates@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.1.tgz#643a92caf894566f91b2b986d2c66950a8e2fb87" + integrity sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA== + dependencies: + node-modules-regexp "^1.0.0" + +pn@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb" + integrity sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA== + +posix-character-classes@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= + +postcss-calc@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.1.tgz#36d77bab023b0ecbb9789d84dcb23c4941145436" + integrity sha512-oXqx0m6tb4N3JGdmeMSc/i91KppbYsFZKdH0xMOqK8V1rJlzrKlTdokz8ozUXLVejydRN6u2IddxpcijRj2FqQ== + dependencies: + css-unit-converter "^1.1.1" + postcss "^7.0.5" + postcss-selector-parser "^5.0.0-rc.4" + postcss-value-parser "^3.3.1" + +postcss-colormin@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-4.0.3.tgz#ae060bce93ed794ac71264f08132d550956bd381" + integrity sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw== + dependencies: + browserslist "^4.0.0" + color "^3.0.0" + has "^1.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-convert-values@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz#ca3813ed4da0f812f9d43703584e449ebe189a7f" + integrity sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ== + dependencies: + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-discard-comments@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz#1fbabd2c246bff6aaad7997b2b0918f4d7af4033" + integrity sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg== + dependencies: + postcss "^7.0.0" + +postcss-discard-duplicates@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz#3fe133cd3c82282e550fc9b239176a9207b784eb" + integrity sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ== + dependencies: + postcss "^7.0.0" + +postcss-discard-empty@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz#c8c951e9f73ed9428019458444a02ad90bb9f765" + integrity sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w== + dependencies: + postcss "^7.0.0" + +postcss-discard-overridden@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz#652aef8a96726f029f5e3e00146ee7a4e755ff57" + integrity sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg== + dependencies: + postcss "^7.0.0" + +postcss-merge-longhand@^4.0.11: + version "4.0.11" + resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz#62f49a13e4a0ee04e7b98f42bb16062ca2549e24" + integrity sha512-alx/zmoeXvJjp7L4mxEMjh8lxVlDFX1gqWHzaaQewwMZiVhLo42TEClKaeHbRf6J7j82ZOdTJ808RtN0ZOZwvw== + dependencies: + css-color-names "0.0.4" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + stylehacks "^4.0.0" + +postcss-merge-rules@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz#362bea4ff5a1f98e4075a713c6cb25aefef9a650" + integrity sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ== + dependencies: + browserslist "^4.0.0" + caniuse-api "^3.0.0" + cssnano-util-same-parent "^4.0.0" + postcss "^7.0.0" + postcss-selector-parser "^3.0.0" + vendors "^1.0.0" + +postcss-minify-font-values@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz#cd4c344cce474343fac5d82206ab2cbcb8afd5a6" + integrity sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg== + dependencies: + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-minify-gradients@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz#93b29c2ff5099c535eecda56c4aa6e665a663471" + integrity sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q== + dependencies: + cssnano-util-get-arguments "^4.0.0" + is-color-stop "^1.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-minify-params@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz#6b9cef030c11e35261f95f618c90036d680db874" + integrity sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg== + dependencies: + alphanum-sort "^1.0.0" + browserslist "^4.0.0" + cssnano-util-get-arguments "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + uniqs "^2.0.0" + +postcss-minify-selectors@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz#e2e5eb40bfee500d0cd9243500f5f8ea4262fbd8" + integrity sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g== + dependencies: + alphanum-sort "^1.0.0" + has "^1.0.0" + postcss "^7.0.0" + postcss-selector-parser "^3.0.0" + +postcss-modules-extract-imports@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.1.0.tgz#b614c9720be6816eaee35fb3a5faa1dba6a05ddb" + integrity sha1-thTJcgvmgW6u41+zpfqh26agXds= + dependencies: + postcss "^6.0.1" + +postcss-modules-local-by-default@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz#f7d80c398c5a393fa7964466bd19500a7d61c069" + integrity sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk= + dependencies: + css-selector-tokenizer "^0.7.0" + postcss "^6.0.1" + +postcss-modules-scope@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz#d6ea64994c79f97b62a72b426fbe6056a194bb90" + integrity sha1-1upkmUx5+XtipytCb75gVqGUu5A= + dependencies: + css-selector-tokenizer "^0.7.0" + postcss "^6.0.1" + +postcss-modules-values@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz#ecffa9d7e192518389f42ad0e83f72aec456ea20" + integrity sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA= + dependencies: + icss-replace-symbols "^1.1.0" + postcss "^6.0.1" + +postcss-modules@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/postcss-modules/-/postcss-modules-1.4.1.tgz#8aa35bd3461db67e27377a7ce770d77b654a84ef" + integrity sha512-btTrbK+Xc3NBuYF8TPBjCMRSp5h6NoQ1iVZ6WiDQENIze6KIYCSf0+UFQuV3yJ7gRHA+4AAtF8i2jRvUpbBMMg== + dependencies: + css-modules-loader-core "^1.1.0" + generic-names "^1.0.3" + lodash.camelcase "^4.3.0" + postcss "^7.0.1" + string-hash "^1.1.1" + +postcss-normalize-charset@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz#8b35add3aee83a136b0471e0d59be58a50285dd4" + integrity sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g== + dependencies: + postcss "^7.0.0" + +postcss-normalize-display-values@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz#0dbe04a4ce9063d4667ed2be476bb830c825935a" + integrity sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ== + dependencies: + cssnano-util-get-match "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-positions@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz#05f757f84f260437378368a91f8932d4b102917f" + integrity sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA== + dependencies: + cssnano-util-get-arguments "^4.0.0" + has "^1.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-repeat-style@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz#c4ebbc289f3991a028d44751cbdd11918b17910c" + integrity sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q== + dependencies: + cssnano-util-get-arguments "^4.0.0" + cssnano-util-get-match "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-string@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz#cd44c40ab07a0c7a36dc5e99aace1eca4ec2690c" + integrity sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA== + dependencies: + has "^1.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-timing-functions@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz#8e009ca2a3949cdaf8ad23e6b6ab99cb5e7d28d9" + integrity sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A== + dependencies: + cssnano-util-get-match "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-unicode@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz#841bd48fdcf3019ad4baa7493a3d363b52ae1cfb" + integrity sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg== + dependencies: + browserslist "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-url@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz#10e437f86bc7c7e58f7b9652ed878daaa95faae1" + integrity sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA== + dependencies: + is-absolute-url "^2.0.0" + normalize-url "^3.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-whitespace@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz#bf1d4070fe4fcea87d1348e825d8cc0c5faa7d82" + integrity sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA== + dependencies: + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-ordered-values@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz#0cf75c820ec7d5c4d280189559e0b571ebac0eee" + integrity sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw== + dependencies: + cssnano-util-get-arguments "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-reduce-initial@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz#7fd42ebea5e9c814609639e2c2e84ae270ba48df" + integrity sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA== + dependencies: + browserslist "^4.0.0" + caniuse-api "^3.0.0" + has "^1.0.0" + postcss "^7.0.0" + +postcss-reduce-transforms@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz#17efa405eacc6e07be3414a5ca2d1074681d4e29" + integrity sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg== + dependencies: + cssnano-util-get-match "^4.0.0" + has "^1.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-selector-parser@6.0.2, postcss-selector-parser@^6.0.0: + version "6.0.2" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz#934cf799d016c83411859e09dcecade01286ec5c" + integrity sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg== + dependencies: + cssesc "^3.0.0" + indexes-of "^1.0.1" + uniq "^1.0.1" + +postcss-selector-parser@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz#4f875f4afb0c96573d5cf4d74011aee250a7e865" + integrity sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU= + dependencies: + dot-prop "^4.1.1" + indexes-of "^1.0.1" + uniq "^1.0.1" + +postcss-selector-parser@^5.0.0-rc.4: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz#249044356697b33b64f1a8f7c80922dddee7195c" + integrity sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ== + dependencies: + cssesc "^2.0.0" + indexes-of "^1.0.1" + uniq "^1.0.1" + +postcss-svgo@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-4.0.2.tgz#17b997bc711b333bab143aaed3b8d3d6e3d38258" + integrity sha512-C6wyjo3VwFm0QgBy+Fu7gCYOkCmgmClghO+pjcxvrcBKtiKt0uCF+hvbMO1fyv5BMImRK90SMb+dwUnfbGd+jw== + dependencies: + is-svg "^3.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + svgo "^1.0.0" + +postcss-unique-selectors@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz#9446911f3289bfd64c6d680f073c03b1f9ee4bac" + integrity sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg== + dependencies: + alphanum-sort "^1.0.0" + postcss "^7.0.0" + uniqs "^2.0.0" + +postcss-value-parser@^3.0.0, postcss-value-parser@^3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" + integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== + +postcss@6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.1.tgz#000dbd1f8eef217aa368b9a212c5fc40b2a8f3f2" + integrity sha1-AA29H47vIXqjaLmiEsX8QLKo8/I= + dependencies: + chalk "^1.1.3" + source-map "^0.5.6" + supports-color "^3.2.3" + +postcss@^6.0.1: + version "6.0.23" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.23.tgz#61c82cc328ac60e677645f979054eb98bc0e3324" + integrity sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag== + dependencies: + chalk "^2.4.1" + source-map "^0.6.1" + supports-color "^5.4.0" + +postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.17, postcss@^7.0.5: + version "7.0.23" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.23.tgz#9f9759fad661b15964f3cfc3140f66f1e05eadc1" + integrity sha512-hOlMf3ouRIFXD+j2VJecwssTwbvsPGJVMzupptg+85WA+i7MwyrydmQAgY3R+m0Bc0exunhbJmijy8u8+vufuQ== + dependencies: + chalk "^2.4.2" + source-map "^0.6.1" + supports-color "^6.1.0" + +posthtml-parser@^0.4.1: + version "0.4.2" + resolved "https://registry.yarnpkg.com/posthtml-parser/-/posthtml-parser-0.4.2.tgz#a132bbdf0cd4bc199d34f322f5c1599385d7c6c1" + integrity sha512-BUIorsYJTvS9UhXxPTzupIztOMVNPa/HtAm9KHni9z6qEfiJ1bpOBL5DfUOL9XAc3XkLIEzBzpph+Zbm4AdRAg== + dependencies: + htmlparser2 "^3.9.2" + +posthtml-render@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/posthtml-render/-/posthtml-render-1.1.5.tgz#387934e85438a3de77085fbc7d264efb00bd0e0f" + integrity sha512-yvt54j0zCBHQVEFAuR+yHld8CZrCa/E1Z/OcFNCV1IEWTLVxT8O7nYnM4IIw1CD4r8kaRd3lc42+0lgCKgm87w== + +posthtml@^0.11.3: + version "0.11.6" + resolved "https://registry.yarnpkg.com/posthtml/-/posthtml-0.11.6.tgz#e349d51af7929d0683b9d8c3abd8166beecc90a8" + integrity sha512-C2hrAPzmRdpuL3iH0TDdQ6XCc9M7Dcc3zEW5BLerY65G4tWWszwv6nG/ksi6ul5i2mx22ubdljgktXCtNkydkw== + dependencies: + posthtml-parser "^0.4.1" + posthtml-render "^1.1.5" + +posthtml@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/posthtml/-/posthtml-0.12.0.tgz#6e2a2fcd774eaed1a419a95c5cc3a92b676a40a6" + integrity sha512-aNUEP/SfKUXAt+ghG51LC5MmafChBZeslVe/SSdfKIgLGUVRE68mrMF4V8XbH07ZifM91tCSuxY3eHIFLlecQw== + dependencies: + posthtml-parser "^0.4.1" + posthtml-render "^1.1.5" + +prebuild-install@^5.2.5: + version "5.3.3" + resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-5.3.3.tgz#ef4052baac60d465f5ba6bf003c9c1de79b9da8e" + integrity sha512-GV+nsUXuPW2p8Zy7SarF/2W/oiK8bFQgJcncoJ0d7kRpekEA0ftChjfEaF9/Y+QJEc/wFR7RAEa8lYByuUIe2g== + dependencies: + detect-libc "^1.0.3" + expand-template "^2.0.3" + github-from-package "0.0.0" + minimist "^1.2.0" + mkdirp "^0.5.1" + napi-build-utils "^1.0.1" + node-abi "^2.7.0" + noop-logger "^0.1.1" + npmlog "^4.0.1" + pump "^3.0.0" + rc "^1.2.7" + simple-get "^3.0.3" + tar-fs "^2.0.0" + tunnel-agent "^0.6.0" + which-pm-runs "^1.0.0" + +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= + +prettier@^1.19.1: + version "1.19.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb" + integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew== + +pretty-ms@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/pretty-ms/-/pretty-ms-5.1.0.tgz#b906bdd1ec9e9799995c372e2b1c34f073f95384" + integrity sha512-4gaK1skD2gwscCfkswYQRmddUb2GJZtzDGRjHWadVHtK/DIKFufa12MvES6/xu1tVbUYeia5bmLcwJtZJQUqnw== + dependencies: + parse-ms "^2.1.0" + +private@^0.1.6: + version "0.1.8" + resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" + integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +process@^0.11.10: + version "0.11.10" + resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= + +prop-types@^15.5.10, prop-types@^15.6.2: + version "15.7.2" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" + integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== + dependencies: + loose-envify "^1.4.0" + object-assign "^4.1.1" + react-is "^16.8.1" + +proto-list@~1.2.1: + version "1.2.4" + resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" + integrity sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk= + +pseudomap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= + +psl@^1.1.24, psl@^1.1.28: + version "1.4.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.4.0.tgz#5dd26156cdb69fa1fdb8ab1991667d3f80ced7c2" + integrity sha512-HZzqCGPecFLyoRj5HLfuDSKYTJkAfB5thKBIkRHtGjWwY7p1dAyveIbXIq4tO0KYfDF2tHqPUgY9SDnGm00uFw== + +public-encrypt@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" + integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== + dependencies: + bn.js "^4.1.0" + browserify-rsa "^4.0.0" + create-hash "^1.1.0" + parse-asn1 "^5.0.0" + randombytes "^2.0.1" + safe-buffer "^5.1.2" + +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +punycode@1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" + integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= + +punycode@^1.2.4, punycode@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= + +punycode@^2.1.0, punycode@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +purgecss@^1.4.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/purgecss/-/purgecss-1.4.1.tgz#d362e63eb1ed9dd1fa1554b9fd7accb8d54e56dc" + integrity sha512-5jONV/D/3nfa+lC425+LA+OWe5/LDn4a79cac+TnzJq3VczwnWlpIDdW275hHsGhkzIlqATQsYFLW7or0cSwNQ== + dependencies: + glob "^7.1.3" + postcss "^7.0.14" + postcss-selector-parser "^6.0.0" + yargs "^14.0.0" + +q@^1.1.2: + version "1.5.1" + resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" + integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= + +qs@~6.5.2: + version "6.5.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" + integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== + +querystring-es3@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" + integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM= + +querystring@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" + integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= + +quote-stream@^1.0.1, quote-stream@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/quote-stream/-/quote-stream-1.0.2.tgz#84963f8c9c26b942e153feeb53aae74652b7e0b2" + integrity sha1-hJY/jJwmuULhU/7rU6rnRlK34LI= + dependencies: + buffer-equal "0.0.1" + minimist "^1.1.3" + through2 "^2.0.0" + +randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +randomfill@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" + integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== + dependencies: + randombytes "^2.0.5" + safe-buffer "^5.1.0" + +rc@^1.2.7: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + +react-dom@^16.12.0: + version "16.12.0" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.12.0.tgz#0da4b714b8d13c2038c9396b54a92baea633fe11" + integrity sha512-LMxFfAGrcS3kETtQaCkTKjMiifahaMySFDn71fZUNpPHZQEzmk/GiAeIT8JSOrHB23fnuCOMruL2a8NYlw+8Gw== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + prop-types "^15.6.2" + scheduler "^0.18.0" + +react-is@^16.8.1: + version "16.12.0" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.12.0.tgz#2cc0fe0fba742d97fd527c42a13bec4eeb06241c" + integrity sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q== + +react-reconciler@^0.21.0: + version "0.21.0" + resolved "https://registry.yarnpkg.com/react-reconciler/-/react-reconciler-0.21.0.tgz#8180342ab3c8295f860025a86d0a03742a294ea7" + integrity sha512-h4Rl3L3O6G9V4Ff+F+tCXX8ElDVn0Psk/odT+NPWeA55Yk5G7+kHT8D+Q3yE+51C72LbrYcX6OfLmCZ/7Nx9cw== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + prop-types "^15.6.2" + scheduler "^0.15.0" + +react-refresh@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.6.0.tgz#81971b8f3c8c05aaa6ce87491ae41b396133f896" + integrity sha512-Wv48N+GFt6Azvtl/LMvzNW9hvEyJdRQ48oVKIBAN7hjtvXXfxfVJXbPl/11SM1C/NIquIFXzzWCo6ZNH0I8I4g== + +react-virtualized-auto-sizer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.2.tgz#a61dd4f756458bbf63bd895a92379f9b70f803bd" + integrity sha512-MYXhTY1BZpdJFjUovvYHVBmkq79szK/k7V3MO+36gJkWGkrXKtyr4vCPtpphaTLRAdDNoYEYFZWE8LjN+PIHNg== + +react@^16.12.0, react@^16.7.0: + version "16.12.0" + resolved "https://registry.yarnpkg.com/react/-/react-16.12.0.tgz#0c0a9c6a142429e3614834d5a778e18aa78a0b83" + integrity sha512-fglqy3k5E+81pA8s+7K0/T3DBCF0ZDOher1elBFzF7O6arXJgzyu/FW+COxFvAWXJoJN9KIZbT2LXlukwphYTA== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + prop-types "^15.6.2" + +readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.3, readable-stream@~2.3.6: + version "2.3.6" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" + integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@^3.0.0, readable-stream@^3.0.1, readable-stream@^3.1.1: + version "3.4.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.4.0.tgz#a51c26754658e0a3c21dbf59163bd45ba6f447fc" + integrity sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +regenerate-unicode-properties@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz#ef51e0f0ea4ad424b77bf7cb41f3e015c70a3f0e" + integrity sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA== + dependencies: + regenerate "^1.4.0" + +regenerate@^1.2.1, regenerate@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" + integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg== + +regenerator-runtime@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" + integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== + +regenerator-transform@^0.14.0: + version "0.14.1" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.1.tgz#3b2fce4e1ab7732c08f665dfdb314749c7ddd2fb" + integrity sha512-flVuee02C3FKRISbxhXl9mGzdbWUVHubl1SMaknjxkFB1/iqpJhArQUvRxOOPEc/9tAiX0BaQ28FJH10E4isSQ== + dependencies: + private "^0.1.6" + +regex-not@^1.0.0, regex-not@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== + dependencies: + extend-shallow "^3.0.2" + safe-regex "^1.1.0" + +regexpu-core@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-1.0.0.tgz#86a763f58ee4d7c2f6b102e4764050de7ed90c6b" + integrity sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs= + dependencies: + regenerate "^1.2.1" + regjsgen "^0.2.0" + regjsparser "^0.1.4" + +regexpu-core@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.6.0.tgz#2037c18b327cfce8a6fea2a4ec441f2432afb8b6" + integrity sha512-YlVaefl8P5BnFYOITTNzDvan1ulLOiXJzCNZxduTIosN17b87h3bvG9yHMoHaRuo88H4mQ06Aodj5VtYGGGiTg== + dependencies: + regenerate "^1.4.0" + regenerate-unicode-properties "^8.1.0" + regjsgen "^0.5.0" + regjsparser "^0.6.0" + unicode-match-property-ecmascript "^1.0.4" + unicode-match-property-value-ecmascript "^1.1.0" + +regjsgen@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" + integrity sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc= + +regjsgen@^0.5.0: + version "0.5.1" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.1.tgz#48f0bf1a5ea205196929c0d9798b42d1ed98443c" + integrity sha512-5qxzGZjDs9w4tzT3TPhCJqWdCc3RLYwy9J2NB0nm5Lz+S273lvWcpjaTGHsT1dc6Hhfq41uSEOw8wBmxrKOuyg== + +regjsparser@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" + integrity sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw= + dependencies: + jsesc "~0.5.0" + +regjsparser@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.0.tgz#f1e6ae8b7da2bae96c99399b868cd6c933a2ba9c" + integrity sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ== + dependencies: + jsesc "~0.5.0" + +repeat-element@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" + integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== + +repeat-string@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= + +request-promise-core@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.3.tgz#e9a3c081b51380dfea677336061fea879a829ee9" + integrity sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ== + dependencies: + lodash "^4.17.15" + +request-promise-native@^1.0.5: + version "1.0.8" + resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.8.tgz#a455b960b826e44e2bf8999af64dff2bfe58cb36" + integrity sha512-dapwLGqkHtwL5AEbfenuzjTYg35Jd6KPytsC2/TLkVMz8rm+tNt72MGUWT1RP/aYawMpN6HqbNGBQaRcBtjQMQ== + dependencies: + request-promise-core "1.1.3" + stealthy-require "^1.1.1" + tough-cookie "^2.3.3" + +request@^2.88.0: + version "2.88.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" + integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + har-validator "~5.1.0" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + oauth-sign "~0.9.0" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.4.3" + tunnel-agent "^0.6.0" + uuid "^3.3.2" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= + +resolve-from@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" + integrity sha1-six699nWiBvItuZTM17rywoYh0g= + +resolve-url@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= + +resolve@^1.1.5, resolve@^1.12.0, resolve@^1.3.2: + version "1.12.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.12.0.tgz#3fc644a35c84a48554609ff26ec52b66fa577df6" + integrity sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w== + dependencies: + path-parse "^1.0.6" + +restore-cursor@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" + integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368= + dependencies: + onetime "^2.0.0" + signal-exit "^3.0.2" + +ret@~0.1.10: + version "0.1.15" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== + +reusify@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rgb-regex@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/rgb-regex/-/rgb-regex-1.0.1.tgz#c0e0d6882df0e23be254a475e8edd41915feaeb1" + integrity sha1-wODWiC3w4jviVKR16O3UGRX+rrE= + +rgba-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3" + integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM= + +rimraf@^2.6.2: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + +ripemd160@^2.0.0, ripemd160@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" + integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + +run-parallel@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" + integrity sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q== + +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" + integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== + +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= + dependencies: + ret "~0.1.10" + +"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +safer-eval@^1.3.0: + version "1.3.5" + resolved "https://registry.yarnpkg.com/safer-eval/-/safer-eval-1.3.5.tgz#a75a1193a4e1dfadd34a8c87ad08e7b978c494b1" + integrity sha512-BJ//K2Y+EgCbOHEsDGS5YahYBcYy7JcFpKDo2ba5t4MnOGHYtk7HvQkcxTDFvjQvJ0CRcdas/PyF+gTTCay+3w== + dependencies: + clones "^1.2.0" + +sax@~1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== + +saxes@^3.1.9: + version "3.1.11" + resolved "https://registry.yarnpkg.com/saxes/-/saxes-3.1.11.tgz#d59d1fd332ec92ad98a2e0b2ee644702384b1c5b" + integrity sha512-Ydydq3zC+WYDJK1+gRxRapLIED9PWeSuuS41wqyoRmzvhhh9nc+QQrVMKJYzJFULazeGhzSV0QleN2wD3boh2g== + dependencies: + xmlchars "^2.1.1" + +scheduler@^0.15.0: + version "0.15.0" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.15.0.tgz#6bfcf80ff850b280fed4aeecc6513bc0b4f17f8e" + integrity sha512-xAefmSfN6jqAa7Kuq7LIJY0bwAPG3xlCj0HMEBQk1lxYiDKZscY2xJ5U/61ZTrYbmNQbXa+gc7czPkVo11tnCg== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + +scheduler@^0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.18.0.tgz#5901ad6659bc1d8f3fdaf36eb7a67b0d6746b1c4" + integrity sha512-agTSHR1Nbfi6ulI0kYNK0203joW2Y5W4po4l+v03tOoiJKpTBbxpNhWDvqc/4IcOw+KLmSiQLTasZ4cab2/UWQ== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + +semver@^5.4.1, semver@^5.5.0, semver@^5.6.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + +semver@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +serialize-to-js@^1.1.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/serialize-to-js/-/serialize-to-js-1.2.2.tgz#1a567b0c9bf557bc7d7b77b503dfae0a8218d15d" + integrity sha512-mUc8vA5iJghe+O+3s0YDGFLMJcqitVFk787YKiv8a4sf6RX5W0u81b+gcHrp15O0fFa010dRBVZvwcKXOWsL9Q== + dependencies: + js-beautify "^1.8.9" + safer-eval "^1.3.0" + +set-blocking@^2.0.0, set-blocking@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + +set-value@^2.0.0, set-value@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" + integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.3" + split-string "^3.0.1" + +setimmediate@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= + +sha.js@^2.4.0, sha.js@^2.4.8: + version "2.4.11" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" + integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +shallow-copy@~0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/shallow-copy/-/shallow-copy-0.0.1.tgz#415f42702d73d810330292cc5ee86eae1a11a170" + integrity sha1-QV9CcC1z2BAzApLMXuhurhoRoXA= + +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= + dependencies: + shebang-regex "^1.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= + +sigmund@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" + integrity sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA= + +signal-exit@^3.0.0, signal-exit@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" + integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= + +simple-concat@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.0.tgz#7344cbb8b6e26fb27d66b2fc86f9f6d5997521c6" + integrity sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY= + +simple-get@^3.0.3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-3.1.0.tgz#b45be062435e50d159540b576202ceec40b9c6b3" + integrity sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA== + dependencies: + decompress-response "^4.2.0" + once "^1.3.1" + simple-concat "^1.0.0" + +simple-swizzle@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" + integrity sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo= + dependencies: + is-arrayish "^0.3.1" + +slice-ansi@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d" + integrity sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg== + dependencies: + is-fullwidth-code-point "^2.0.0" + +snapdragon-node@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== + dependencies: + define-property "^1.0.0" + isobject "^3.0.0" + snapdragon-util "^3.0.1" + +snapdragon-util@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== + dependencies: + kind-of "^3.2.0" + +snapdragon@^0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== + dependencies: + base "^0.11.1" + debug "^2.2.0" + define-property "^0.2.5" + extend-shallow "^2.0.1" + map-cache "^0.2.2" + source-map "^0.5.6" + source-map-resolve "^0.5.0" + use "^3.1.0" + +source-map-resolve@^0.5.0: + version "0.5.2" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" + integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA== + dependencies: + atob "^2.1.1" + decode-uri-component "^0.2.0" + resolve-url "^0.2.1" + source-map-url "^0.4.0" + urix "^0.1.0" + +source-map-support@~0.5.10, source-map-support@~0.5.12: + version "0.5.16" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042" + integrity sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map-url@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" + integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= + +source-map@^0.5.0, source-map@^0.5.6: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= + +source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +source-map@^0.7.3: + version "0.7.3" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" + integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== + +split-string@^3.0.1, split-string@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== + dependencies: + extend-shallow "^3.0.0" + +split2@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/split2/-/split2-3.1.1.tgz#c51f18f3e06a8c4469aaab487687d8d956160bb6" + integrity sha512-emNzr1s7ruq4N+1993yht631/JH+jaj0NYBosuKmLcq+JkGQ9MmTw1RB1fGaTCzUuseRIClrlSLHRNYGwWQ58Q== + dependencies: + readable-stream "^3.0.0" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + +sshpk@^1.7.0: + version "1.16.1" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" + integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" + ecc-jsbn "~0.1.1" + getpass "^0.1.1" + jsbn "~0.1.0" + safer-buffer "^2.0.2" + tweetnacl "~0.14.0" + +stable@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" + integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== + +static-eval@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/static-eval/-/static-eval-2.0.3.tgz#cb62fc79946bd4d5f623a45ad428233adace4d72" + integrity sha512-zsxDGucfAh8T339sSKgpFbvg15Fms2IVaJGC+jqp0bVsxhcpM+iMeAI8weNo8dmf4OblgifTBUoyk1vGVtYw2w== + dependencies: + escodegen "^1.11.1" + +static-extend@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= + dependencies: + define-property "^0.2.5" + object-copy "^0.1.0" + +static-module@^2.2.0: + version "2.2.5" + resolved "https://registry.yarnpkg.com/static-module/-/static-module-2.2.5.tgz#bd40abceae33da6b7afb84a0e4329ff8852bfbbf" + integrity sha512-D8vv82E/Kpmz3TXHKG8PPsCPg+RAX6cbCOyvjM6x04qZtQ47EtJFVwRsdov3n5d6/6ynrOY9XB4JkaZwB2xoRQ== + dependencies: + concat-stream "~1.6.0" + convert-source-map "^1.5.1" + duplexer2 "~0.1.4" + escodegen "~1.9.0" + falafel "^2.1.0" + has "^1.0.1" + magic-string "^0.22.4" + merge-source-map "1.0.4" + object-inspect "~1.4.0" + quote-stream "~1.0.2" + readable-stream "~2.3.3" + shallow-copy "~0.0.1" + static-eval "^2.0.0" + through2 "~2.0.3" + +statuses@~1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= + +stealthy-require@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" + integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= + +stream-browserify@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" + integrity sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg== + dependencies: + inherits "~2.0.1" + readable-stream "^2.0.2" + +stream-http@^2.7.2: + version "2.8.3" + resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" + integrity sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw== + dependencies: + builtin-status-codes "^3.0.0" + inherits "^2.0.1" + readable-stream "^2.3.6" + to-arraybuffer "^1.0.0" + xtend "^4.0.0" + +string-hash@^1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/string-hash/-/string-hash-1.1.3.tgz#e8aafc0ac1855b4666929ed7dd1275df5d6c811b" + integrity sha1-6Kr8CsGFW0Zmkp7X3RJ1311sgRs= + +string-length@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/string-length/-/string-length-2.0.0.tgz#d40dbb686a3ace960c1cffca562bf2c45f8363ed" + integrity sha1-1A27aGo6zpYMHP/KVivyxF+DY+0= + dependencies: + astral-regex "^1.0.0" + strip-ansi "^4.0.0" + +string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +string-width@^3.0.0, string-width@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== + dependencies: + emoji-regex "^7.0.1" + is-fullwidth-code-point "^2.0.0" + strip-ansi "^5.1.0" + +string.prototype.trimleft@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz#6cc47f0d7eb8d62b0f3701611715a3954591d634" + integrity sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw== + dependencies: + define-properties "^1.1.3" + function-bind "^1.1.1" + +string.prototype.trimright@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz#669d164be9df9b6f7559fa8e89945b168a5a6c58" + integrity sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg== + dependencies: + define-properties "^1.1.3" + function-bind "^1.1.1" + +string_decoder@^1.0.0, string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= + dependencies: + ansi-regex "^3.0.0" + +strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + dependencies: + ansi-regex "^4.1.0" + +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + +stylehacks@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-4.0.3.tgz#6718fcaf4d1e07d8a1318690881e8d96726a71d5" + integrity sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g== + dependencies: + browserslist "^4.0.0" + postcss "^7.0.0" + postcss-selector-parser "^3.0.0" + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= + +supports-color@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" + integrity sha1-ZawFBLOVQXHYpklGsq48u4pfVPY= + dependencies: + has-flag "^1.0.0" + +supports-color@^5.3.0, supports-color@^5.4.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" + integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== + dependencies: + has-flag "^3.0.0" + +svgo@^1.0.0, svgo@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.2.tgz#b6dc511c063346c9e415b81e43401145b96d4167" + integrity sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw== + dependencies: + chalk "^2.4.1" + coa "^2.0.2" + css-select "^2.0.0" + css-select-base-adapter "^0.1.1" + css-tree "1.0.0-alpha.37" + csso "^4.0.2" + js-yaml "^3.13.1" + mkdirp "~0.5.1" + object.values "^1.1.0" + sax "~1.2.4" + stable "^0.1.8" + unquote "~1.1.1" + util.promisify "~1.0.0" + +symbol-tree@^3.2.2: + version "3.2.4" + resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" + integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== + +tar-fs@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.0.0.tgz#677700fc0c8b337a78bee3623fdc235f21d7afad" + integrity sha512-vaY0obB6Om/fso8a8vakQBzwholQ7v5+uy+tF3Ozvxv1KNezmVQAiWtcNmMHFSFPqL3dJA8ha6gdtFbfX9mcxA== + dependencies: + chownr "^1.1.1" + mkdirp "^0.5.1" + pump "^3.0.0" + tar-stream "^2.0.0" + +tar-stream@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.1.0.tgz#d1aaa3661f05b38b5acc9b7020efdca5179a2cc3" + integrity sha512-+DAn4Nb4+gz6WZigRzKEZl1QuJVOLtAwwF+WUxy1fJ6X63CaGaUAxJRD2KEn1OMfcbCjySTYpNC6WmfQoIEOdw== + dependencies: + bl "^3.0.0" + end-of-stream "^1.4.1" + fs-constants "^1.0.0" + inherits "^2.0.3" + readable-stream "^3.1.1" + +terser@^3.7.3: + version "3.17.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-3.17.0.tgz#f88ffbeda0deb5637f9d24b0da66f4e15ab10cb2" + integrity sha512-/FQzzPJmCpjAH9Xvk2paiWrFq+5M6aVOf+2KRbwhByISDX/EujxsK+BAvrhb6H+2rtrLCHK9N01wO014vrIwVQ== + dependencies: + commander "^2.19.0" + source-map "~0.6.1" + source-map-support "~0.5.10" + +terser@^4.0.0, terser@^4.3.9: + version "4.4.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.4.0.tgz#22c46b4817cf4c9565434bfe6ad47336af259ac3" + integrity sha512-oDG16n2WKm27JO8h4y/w3iqBGAOSCtq7k8dRmrn4Wf9NouL0b2WpMHGChFGZq4nFAQy1FsNJrVQHfurXOSTmOA== + dependencies: + commander "^2.20.0" + source-map "~0.6.1" + source-map-support "~0.5.12" + +through2@^2.0.0, through2@~2.0.3: + version "2.0.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" + integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== + dependencies: + readable-stream "~2.3.6" + xtend "~4.0.1" + +timers-browserify@^2.0.4: + version "2.0.11" + resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.11.tgz#800b1f3eee272e5bc53ee465a04d0e804c31211f" + integrity sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ== + dependencies: + setimmediate "^1.0.4" + +timsort@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" + integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= + +tiny-inflate@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tiny-inflate/-/tiny-inflate-1.0.3.tgz#122715494913a1805166aaf7c93467933eea26c4" + integrity sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw== + +to-arraybuffer@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" + integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= + +to-fast-properties@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" + integrity sha1-uDVx+k2MJbguIxsG46MFXeTKGkc= + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= + +to-object-path@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= + dependencies: + kind-of "^3.0.2" + +to-regex-range@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= + dependencies: + is-number "^3.0.0" + repeat-string "^1.6.1" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +to-regex@^3.0.1, to-regex@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== + dependencies: + define-property "^2.0.2" + extend-shallow "^3.0.2" + regex-not "^1.0.2" + safe-regex "^1.1.0" + +tough-cookie@^2.3.3, tough-cookie@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== + dependencies: + psl "^1.1.28" + punycode "^2.1.1" + +tough-cookie@~2.4.3: + version "2.4.3" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" + integrity sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ== + dependencies: + psl "^1.1.24" + punycode "^1.4.1" + +tr46@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09" + integrity sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk= + dependencies: + punycode "^2.1.0" + +tslib@^1.9.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" + integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== + +tty-browserify@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" + integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY= + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= + dependencies: + safe-buffer "^5.0.1" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= + +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= + dependencies: + prelude-ls "~1.1.2" + +type-fest@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" + integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= + +uncss@^0.17.2: + version "0.17.2" + resolved "https://registry.yarnpkg.com/uncss/-/uncss-0.17.2.tgz#fac1c2429be72108e8a47437c647d58cf9ea66f1" + integrity sha512-hu2HquwDItuGDem4YsJROdAD8SknmWtM24zwhQax6J1se8tPjV1cnwPKhtjodzBaUhaL8Zb3hlGdZ2WAUpbAOg== + dependencies: + commander "^2.20.0" + glob "^7.1.4" + is-absolute-url "^3.0.1" + is-html "^1.1.0" + jsdom "^14.1.0" + lodash "^4.17.15" + postcss "^7.0.17" + postcss-selector-parser "6.0.2" + request "^2.88.0" + +unicode-canonical-property-names-ecmascript@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818" + integrity sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ== + +unicode-match-property-ecmascript@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz#8ed2a32569961bce9227d09cd3ffbb8fed5f020c" + integrity sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg== + dependencies: + unicode-canonical-property-names-ecmascript "^1.0.4" + unicode-property-aliases-ecmascript "^1.0.4" + +unicode-match-property-value-ecmascript@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz#5b4b426e08d13a80365e0d657ac7a6c1ec46a277" + integrity sha512-hDTHvaBk3RmFzvSl0UVrUmC3PuW9wKVnpoUDYH0JDkSIovzw+J5viQmeYHxVSBptubnr7PbH2e0fnpDRQnQl5g== + +unicode-property-aliases-ecmascript@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz#a9cc6cc7ce63a0a3023fc99e341b94431d405a57" + integrity sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw== + +unicode-trie@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/unicode-trie/-/unicode-trie-0.3.1.tgz#d671dddd89101a08bac37b6a5161010602052085" + integrity sha1-1nHd3YkQGgi6w3tqUWEBBgIFIIU= + dependencies: + pako "^0.2.5" + tiny-inflate "^1.0.0" + +union-value@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" + integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== + dependencies: + arr-union "^3.1.0" + get-value "^2.0.6" + is-extendable "^0.1.1" + set-value "^2.0.1" + +uniq@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" + integrity sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8= + +uniqs@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02" + integrity sha1-/+3ks2slKQaW5uFl1KWe25mOawI= + +unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= + +unquote@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/unquote/-/unquote-1.1.1.tgz#8fded7324ec6e88a0ff8b905e7c098cdc086d544" + integrity sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ= + +unset-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= + dependencies: + has-value "^0.3.1" + isobject "^3.0.0" + +uri-js@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" + integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== + dependencies: + punycode "^2.1.0" + +urix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= + +url@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" + integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= + dependencies: + punycode "1.3.2" + querystring "0.2.0" + +use@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" + integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== + +util-deprecate@^1.0.1, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + +util.promisify@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030" + integrity sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA== + dependencies: + define-properties "^1.1.2" + object.getownpropertydescriptors "^2.0.3" + +util@0.10.3: + version "0.10.3" + resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" + integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk= + dependencies: + inherits "2.0.1" + +util@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/util/-/util-0.11.1.tgz#3236733720ec64bb27f6e26f421aaa2e1b588d61" + integrity sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ== + dependencies: + inherits "2.0.3" + +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= + +uuid@^3.3.2: + version "3.3.3" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.3.tgz#4568f0216e78760ee1dbf3a4d2cf53e224112866" + integrity sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ== + +v8-compile-cache@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz#e14de37b31a6d194f5690d67efc4e7f6fc6ab30e" + integrity sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g== + +vendors@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.3.tgz#a6467781abd366217c050f8202e7e50cc9eef8c0" + integrity sha512-fOi47nsJP5Wqefa43kyWSg80qF+Q3XA6MUkgi7Hp1HQaKDQW4cQrK2D0P7mmbFtsV1N89am55Yru/nyEwRubcw== + +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + +vlq@^0.2.2: + version "0.2.3" + resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.3.tgz#8f3e4328cf63b1540c0d67e1b2778386f8975b26" + integrity sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow== + +vm-browserify@^1.0.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" + integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== + +w3c-hr-time@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz#82ac2bff63d950ea9e3189a58a65625fedf19045" + integrity sha1-gqwr/2PZUOqeMYmlimViX+3xkEU= + dependencies: + browser-process-hrtime "^0.1.2" + +w3c-xmlserializer@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-1.1.2.tgz#30485ca7d70a6fd052420a3d12fd90e6339ce794" + integrity sha512-p10l/ayESzrBMYWRID6xbuCKh2Fp77+sA0doRuGn4tTIMrrZVeqfpKjXHY+oDh3K4nLdPgNwMTVP6Vp4pvqbNg== + dependencies: + domexception "^1.0.1" + webidl-conversions "^4.0.2" + xml-name-validator "^3.0.0" + +webidl-conversions@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" + integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== + +whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0" + integrity sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw== + dependencies: + iconv-lite "0.4.24" + +whatwg-mimetype@^2.2.0, whatwg-mimetype@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" + integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g== + +whatwg-url@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06" + integrity sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg== + dependencies: + lodash.sortby "^4.7.0" + tr46 "^1.0.1" + webidl-conversions "^4.0.2" + +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= + +which-pm-runs@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/which-pm-runs/-/which-pm-runs-1.0.0.tgz#670b3afbc552e0b55df6b7780ca74615f23ad1cb" + integrity sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs= + +which@^1.2.9: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +wide-align@^1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== + dependencies: + string-width "^1.0.2 || 2" + +widest-line@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-2.0.1.tgz#7438764730ec7ef4381ce4df82fb98a53142a3fc" + integrity sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA== + dependencies: + string-width "^2.1.1" + +word-wrap@~1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" + integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + +wrap-ansi@^5.0.0, wrap-ansi@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" + integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== + dependencies: + ansi-styles "^3.2.0" + string-width "^3.0.0" + strip-ansi "^5.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +ws@^6.1.2, ws@^6.2.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb" + integrity sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA== + dependencies: + async-limiter "~1.0.0" + +xml-name-validator@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" + integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== + +xmlchars@^2.1.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" + integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== + +xtend@^4.0.0, xtend@~4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + +y18n@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" + integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== + +yallist@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= + +yargs-parser@^15.0.0: + version "15.0.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-15.0.0.tgz#cdd7a97490ec836195f59f3f4dbe5ea9e8f75f08" + integrity sha512-xLTUnCMc4JhxrPEPUYD5IBR1mWCK/aT6+RJ/K29JY2y1vD+FhtgKK0AXRWvI262q3QSffAQuTouFIKUuHX89wQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs@^14.0.0: + version "14.2.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-14.2.2.tgz#2769564379009ff8597cdd38fba09da9b493c4b5" + integrity sha512-/4ld+4VV5RnrynMhPZJ/ZpOCGSCeghMykZ3BhdFBDa9Wy/RH6uEGNWDJog+aUlq+9OM1CFTgtYRW5Is1Po9NOA== + dependencies: + cliui "^5.0.0" + decamelize "^1.2.0" + find-up "^3.0.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^3.0.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^15.0.0" + +yoga-layout-prebuilt@^1.9.3: + version "1.9.3" + resolved "https://registry.yarnpkg.com/yoga-layout-prebuilt/-/yoga-layout-prebuilt-1.9.3.tgz#11e3be29096afe3c284e5d963cc2d628148c1372" + integrity sha512-9SNQpwuEh2NucU83i2KMZnONVudZ86YNcFk9tq74YaqrQfgJWO3yB9uzH1tAg8iqh5c9F5j0wuyJ2z72wcum2w== From aeb7ac0b7bbc7c7f3287099ae5c4c58e3b611292 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Mon, 6 Jan 2020 16:32:33 -0800 Subject: [PATCH 002/116] Auto-align flamegraph labels with edge of screen if scrolled partially off --- src/App.js | 10 +++++++--- src/EventTooltip.css | 4 +--- src/EventTooltip.js | 18 +++++++++++++----- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/App.js b/src/App.js index ea9a50e223086..5640d53861867 100644 --- a/src/App.js +++ b/src/App.js @@ -173,7 +173,10 @@ function getHoveredEvent(data, flamechart, state) { } else { if (flamechart !== null) { const layerIndex = Math.floor( - (canvasMouseY + offsetY - HEADER_HEIGHT_FIXED - REACT_DEVTOOLS_CANVAS_HEIGHT) / + (canvasMouseY + + offsetY - + HEADER_HEIGHT_FIXED - + REACT_DEVTOOLS_CANVAS_HEIGHT) / FLAMECHART_FRAME_HEIGHT ); const layer = flamechart.layers[layerIndex]; @@ -574,13 +577,13 @@ const renderCanvas = memoize( const trimmedName = trimFlamegraphText( context, name, - width - FLAMECHART_TEXT_PADDING * 2 + width - FLAMECHART_TEXT_PADDING * 2 + (x < 0 ? x : 0) ); if (trimmedName !== null) { context.fillStyle = COLORS.PRIORITY_LABEL; context.fillText( trimmedName, - x + FLAMECHART_TEXT_PADDING, + x + FLAMECHART_TEXT_PADDING - (x < 0 ? x : 0), y + FLAMECHART_FRAME_HEIGHT / 2 ); } @@ -688,6 +691,7 @@ function App() { // I would not expect to have to do either of this, // but some of the data being passed in requires it. data = data.filter(Boolean).sort((a, b) => (a.ts > b.ts ? 1 : -1)); + if (data.length > 0) { unstable_batchedUpdates(() => { const processedData = preprocessData(data); diff --git a/src/EventTooltip.css b/src/EventTooltip.css index 660e7f6df34bb..a0939364d29c3 100644 --- a/src/EventTooltip.css +++ b/src/EventTooltip.css @@ -2,6 +2,7 @@ position: absolute; display: inline-block; border-radius: 0.125rem; + max-width: 300px; padding: 0.25rem; user-select: none; pointer-events: none; @@ -33,9 +34,6 @@ .Duration { } -.ComponentName { -} - .ComponentName { font-weight: bold; } diff --git a/src/EventTooltip.js b/src/EventTooltip.js index 92287093742fa..03b6247d2691c 100644 --- a/src/EventTooltip.js +++ b/src/EventTooltip.js @@ -1,7 +1,7 @@ // @flow import prettyMilliseconds from 'pretty-ms'; -import React, { useLayoutEffect, useRef } from 'react'; +import React, { Fragment, useLayoutEffect, useRef } from 'react'; import { COLORS } from './constants'; import { getBatchRange } from './utils'; import useSmartTooltip from './useSmartTooltip'; @@ -91,6 +91,10 @@ export default function EventTooltip({ data, hoveredEvent, state }) { } function formatComponentStack(componentStack) { + if (componentStack == null) { + return null; + } + const lines = componentStack.split('\n').map(line => line.trim()); lines.shift(); @@ -158,10 +162,14 @@ const TooltipReactEvent = ({ color, data, event, tooltipRef }) => {
Timestamp:
{prettyMilliseconds(timestamp)} -
Component stack:
-
-          {formatComponentStack(componentStack)}
-        
+ {componentStack && ( + +
Component stack:
+
+              {formatComponentStack(componentStack)}
+            
+
+ )}
); From eed2ca6a363b5b72a6f391b4fbd890f01c829d45 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Tue, 7 Jan 2020 11:31:34 -0800 Subject: [PATCH 003/116] Config changes --- .prettierignore | 1 + package.json | 5 +- yarn.lock | 1466 +++++++++++++++++++++++++---------------------- 3 files changed, 785 insertions(+), 687 deletions(-) diff --git a/.prettierignore b/.prettierignore index 08e44b6d41837..bd3947a216a21 100644 --- a/.prettierignore +++ b/.prettierignore @@ -2,6 +2,7 @@ package-lock.json yarn.lock .parcel-cache/* node_modules/* +dist/* static/* src/speedscope/* src/tracerbench/* \ No newline at end of file diff --git a/package.json b/package.json index 28ae41422d541..974231af3c9e4 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "license": "MIT", "dependencies": { "array-binsearch": "^1.0.1", + "clipboard-js": "^0.3.6", "d3-hierarchy": "^1.1.9", "lodash.clonedeep": "^4.5.0", "memoize-one": "^5.1.1", @@ -21,7 +22,7 @@ }, "devDependencies": { "parcel": "2.0.0-alpha.3.2", - "prettier": "^1.19.1", - "postcss-modules": "^1.4.1" + "postcss-modules": "^1.4.1", + "prettier": "^1.19.1" } } diff --git a/yarn.lock b/yarn.lock index 04a77f2852374..76e98779e9ccf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10,17 +10,17 @@ "@babel/highlight" "^7.0.0" "@babel/core@^7.0.0": - version "7.7.2" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.7.2.tgz#ea5b99693bcfc058116f42fa1dd54da412b29d91" - integrity sha512-eeD7VEZKfhK1KUXGiyPFettgF3m513f8FoBSWiQ1xTvl1RAopLs42Wp9+Ze911I6H0N9lNqJMDgoZT7gHsipeQ== + version "7.7.7" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.7.7.tgz#ee155d2e12300bcc0cff6a8ad46f2af5063803e9" + integrity sha512-jlSjuj/7z138NLZALxVgrx13AOtqip42ATZP7+kYl53GvDV6+4dCek1mVUo8z8c8Xnw/mx2q3d9HWh3griuesQ== dependencies: "@babel/code-frame" "^7.5.5" - "@babel/generator" "^7.7.2" - "@babel/helpers" "^7.7.0" - "@babel/parser" "^7.7.2" - "@babel/template" "^7.7.0" - "@babel/traverse" "^7.7.2" - "@babel/types" "^7.7.2" + "@babel/generator" "^7.7.7" + "@babel/helpers" "^7.7.4" + "@babel/parser" "^7.7.7" + "@babel/template" "^7.7.4" + "@babel/traverse" "^7.7.4" + "@babel/types" "^7.7.4" convert-source-map "^1.7.0" debug "^4.1.0" json5 "^2.1.0" @@ -29,140 +29,140 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/generator@^7.0.0", "@babel/generator@^7.3.3", "@babel/generator@^7.7.2": - version "7.7.2" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.7.2.tgz#2f4852d04131a5e17ea4f6645488b5da66ebf3af" - integrity sha512-WthSArvAjYLz4TcbKOi88me+KmDJdKSlfwwN8CnUYn9jBkzhq0ZEPuBfkAWIvjJ3AdEV1Cf/+eSQTnp3IDJKlQ== +"@babel/generator@^7.0.0", "@babel/generator@^7.3.3", "@babel/generator@^7.7.4", "@babel/generator@^7.7.7": + version "7.7.7" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.7.7.tgz#859ac733c44c74148e1a72980a64ec84b85f4f45" + integrity sha512-/AOIBpHh/JU1l0ZFS4kiRCBnLi6OTHzh0RPk3h9isBxkkqELtQNFi1Vr/tiG9p1yfoUdKVwISuXWQR+hwwM4VQ== dependencies: - "@babel/types" "^7.7.2" + "@babel/types" "^7.7.4" jsesc "^2.5.1" lodash "^4.17.13" source-map "^0.5.0" -"@babel/helper-annotate-as-pure@^7.0.0", "@babel/helper-annotate-as-pure@^7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.7.0.tgz#efc54032d43891fe267679e63f6860aa7dbf4a5e" - integrity sha512-k50CQxMlYTYo+GGyUGFwpxKVtxVJi9yh61sXZji3zYHccK9RYliZGSTOgci85T+r+0VFN2nWbGM04PIqwfrpMg== +"@babel/helper-annotate-as-pure@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.7.4.tgz#bb3faf1e74b74bd547e867e48f551fa6b098b6ce" + integrity sha512-2BQmQgECKzYKFPpiycoF9tlb5HA4lrVyAmLLVK177EcQAqjVLciUb2/R+n1boQ9y5ENV3uz2ZqiNw7QMBBw1Og== dependencies: - "@babel/types" "^7.7.0" + "@babel/types" "^7.7.4" -"@babel/helper-builder-binary-assignment-operator-visitor@^7.1.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.7.0.tgz#32dd9551d6ed3a5fc2edc50d6912852aa18274d9" - integrity sha512-Cd8r8zs4RKDwMG/92lpZcnn5WPQ3LAMQbCw42oqUh4s7vsSN5ANUZjMel0OOnxDLq57hoDDbai+ryygYfCTOsw== +"@babel/helper-builder-binary-assignment-operator-visitor@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.7.4.tgz#5f73f2b28580e224b5b9bd03146a4015d6217f5f" + integrity sha512-Biq/d/WtvfftWZ9Uf39hbPBYDUo986m5Bb4zhkeYDGUllF43D+nUe5M6Vuo6/8JDK/0YX/uBdeoQpyaNhNugZQ== dependencies: - "@babel/helper-explode-assignable-expression" "^7.7.0" - "@babel/types" "^7.7.0" + "@babel/helper-explode-assignable-expression" "^7.7.4" + "@babel/types" "^7.7.4" -"@babel/helper-builder-react-jsx@^7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.7.0.tgz#c6b8254d305bacd62beb648e4dea7d3ed79f352d" - integrity sha512-LSln3cexwInTMYYoFeVLKnYPPMfWNJ8PubTBs3hkh7wCu9iBaqq1OOyW+xGmEdLxT1nhsl+9SJ+h2oUDYz0l2A== +"@babel/helper-builder-react-jsx@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.7.4.tgz#da188d247508b65375b2c30cf59de187be6b0c66" + integrity sha512-kvbfHJNN9dg4rkEM4xn1s8d1/h6TYNvajy9L1wx4qLn9HFg0IkTsQi4rfBe92nxrPUFcMsHoMV+8rU7MJb3fCA== dependencies: - "@babel/types" "^7.7.0" + "@babel/types" "^7.7.4" esutils "^2.0.0" -"@babel/helper-call-delegate@^7.4.4": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@babel/helper-call-delegate/-/helper-call-delegate-7.7.0.tgz#df8942452c2c1a217335ca7e393b9afc67f668dc" - integrity sha512-Su0Mdq7uSSWGZayGMMQ+z6lnL00mMCnGAbO/R0ZO9odIdB/WNU/VfQKqMQU0fdIsxQYbRjDM4BixIa93SQIpvw== +"@babel/helper-call-delegate@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-call-delegate/-/helper-call-delegate-7.7.4.tgz#621b83e596722b50c0066f9dc37d3232e461b801" + integrity sha512-8JH9/B7J7tCYJ2PpWVpw9JhPuEVHztagNVuQAFBVFYluRMlpG7F1CgKEgGeL6KFqcsIa92ZYVj6DSc0XwmN1ZA== dependencies: - "@babel/helper-hoist-variables" "^7.7.0" - "@babel/traverse" "^7.7.0" - "@babel/types" "^7.7.0" + "@babel/helper-hoist-variables" "^7.7.4" + "@babel/traverse" "^7.7.4" + "@babel/types" "^7.7.4" -"@babel/helper-create-class-features-plugin@^7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.7.0.tgz#bcdc223abbfdd386f94196ae2544987f8df775e8" - integrity sha512-MZiB5qvTWoyiFOgootmRSDV1udjIqJW/8lmxgzKq6oDqxdmHUjeP2ZUOmgHdYjmUVNABqRrHjYAYRvj8Eox/UA== +"@babel/helper-create-class-features-plugin@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.7.4.tgz#fce60939fd50618610942320a8d951b3b639da2d" + integrity sha512-l+OnKACG4uiDHQ/aJT8dwpR+LhCJALxL0mJ6nzjB25e5IPwqV1VOsY7ah6UB1DG+VOXAIMtuC54rFJGiHkxjgA== dependencies: - "@babel/helper-function-name" "^7.7.0" - "@babel/helper-member-expression-to-functions" "^7.7.0" - "@babel/helper-optimise-call-expression" "^7.7.0" + "@babel/helper-function-name" "^7.7.4" + "@babel/helper-member-expression-to-functions" "^7.7.4" + "@babel/helper-optimise-call-expression" "^7.7.4" "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-replace-supers" "^7.7.0" - "@babel/helper-split-export-declaration" "^7.7.0" + "@babel/helper-replace-supers" "^7.7.4" + "@babel/helper-split-export-declaration" "^7.7.4" -"@babel/helper-create-regexp-features-plugin@^7.7.0": - version "7.7.2" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.7.2.tgz#6f20443778c8fce2af2ff4206284afc0ced65db6" - integrity sha512-pAil/ZixjTlrzNpjx+l/C/wJk002Wo7XbbZ8oujH/AoJ3Juv0iN/UTcPUHXKMFLqsfS0Hy6Aow8M31brUYBlQQ== +"@babel/helper-create-regexp-features-plugin@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.7.4.tgz#6d5762359fd34f4da1500e4cff9955b5299aaf59" + integrity sha512-Mt+jBKaxL0zfOIWrfQpnfYCN7/rS6GKx6CCCfuoqVVd+17R8zNDlzVYmIi9qyb2wOk002NsmSTDymkIygDUH7A== dependencies: "@babel/helper-regex" "^7.4.4" regexpu-core "^4.6.0" -"@babel/helper-define-map@^7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.7.0.tgz#60b0e9fd60def9de5054c38afde8c8ee409c7529" - integrity sha512-kPKWPb0dMpZi+ov1hJiwse9dWweZsz3V9rP4KdytnX1E7z3cTNmFGglwklzFPuqIcHLIY3bgKSs4vkwXXdflQA== +"@babel/helper-define-map@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.7.4.tgz#2841bf92eb8bd9c906851546fe6b9d45e162f176" + integrity sha512-v5LorqOa0nVQUvAUTUF3KPastvUt/HzByXNamKQ6RdJRTV7j8rLL+WB5C/MzzWAwOomxDhYFb1wLLxHqox86lg== dependencies: - "@babel/helper-function-name" "^7.7.0" - "@babel/types" "^7.7.0" + "@babel/helper-function-name" "^7.7.4" + "@babel/types" "^7.7.4" lodash "^4.17.13" -"@babel/helper-explode-assignable-expression@^7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.7.0.tgz#db2a6705555ae1f9f33b4b8212a546bc7f9dc3ef" - integrity sha512-CDs26w2shdD1urNUAji2RJXyBFCaR+iBEGnFz3l7maizMkQe3saVw9WtjG1tz8CwbjvlFnaSLVhgnu1SWaherg== +"@babel/helper-explode-assignable-expression@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.7.4.tgz#fa700878e008d85dc51ba43e9fb835cddfe05c84" + integrity sha512-2/SicuFrNSXsZNBxe5UGdLr+HZg+raWBLE9vC98bdYOKX/U6PY0mdGlYUJdtTDPSU0Lw0PNbKKDpwYHJLn2jLg== dependencies: - "@babel/traverse" "^7.7.0" - "@babel/types" "^7.7.0" + "@babel/traverse" "^7.7.4" + "@babel/types" "^7.7.4" -"@babel/helper-function-name@^7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.7.0.tgz#44a5ad151cfff8ed2599c91682dda2ec2c8430a3" - integrity sha512-tDsJgMUAP00Ugv8O2aGEua5I2apkaQO7lBGUq1ocwN3G23JE5Dcq0uh3GvFTChPa4b40AWiAsLvCZOA2rdnQ7Q== +"@babel/helper-function-name@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz#ab6e041e7135d436d8f0a3eca15de5b67a341a2e" + integrity sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ== dependencies: - "@babel/helper-get-function-arity" "^7.7.0" - "@babel/template" "^7.7.0" - "@babel/types" "^7.7.0" + "@babel/helper-get-function-arity" "^7.7.4" + "@babel/template" "^7.7.4" + "@babel/types" "^7.7.4" -"@babel/helper-get-function-arity@^7.0.0", "@babel/helper-get-function-arity@^7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.0.tgz#c604886bc97287a1d1398092bc666bc3d7d7aa2d" - integrity sha512-tLdojOTz4vWcEnHWHCuPN5P85JLZWbm5Fx5ZsMEMPhF3Uoe3O7awrbM2nQ04bDOUToH/2tH/ezKEOR8zEYzqyw== +"@babel/helper-get-function-arity@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz#cb46348d2f8808e632f0ab048172130e636005f0" + integrity sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA== dependencies: - "@babel/types" "^7.7.0" + "@babel/types" "^7.7.4" -"@babel/helper-hoist-variables@^7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.7.0.tgz#b4552e4cfe5577d7de7b183e193e84e4ec538c81" - integrity sha512-LUe/92NqsDAkJjjCEWkNe+/PcpnisvnqdlRe19FahVapa4jndeuJ+FBiTX1rcAKWKcJGE+C3Q3tuEuxkSmCEiQ== +"@babel/helper-hoist-variables@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.7.4.tgz#612384e3d823fdfaaf9fce31550fe5d4db0f3d12" + integrity sha512-wQC4xyvc1Jo/FnLirL6CEgPgPCa8M74tOdjWpRhQYapz5JC7u3NYU1zCVoVAGCE3EaIP9T1A3iW0WLJ+reZlpQ== dependencies: - "@babel/types" "^7.7.0" + "@babel/types" "^7.7.4" -"@babel/helper-member-expression-to-functions@^7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.7.0.tgz#472b93003a57071f95a541ea6c2b098398bcad8a" - integrity sha512-QaCZLO2RtBcmvO/ekOLp8p7R5X2JriKRizeDpm5ChATAFWrrYDcDxPuCIBXKyBjY+i1vYSdcUTMIb8psfxHDPA== +"@babel/helper-member-expression-to-functions@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.7.4.tgz#356438e2569df7321a8326644d4b790d2122cb74" + integrity sha512-9KcA1X2E3OjXl/ykfMMInBK+uVdfIVakVe7W7Lg3wfXUNyS3Q1HWLFRwZIjhqiCGbslummPDnmb7vIekS0C1vw== dependencies: - "@babel/types" "^7.7.0" + "@babel/types" "^7.7.4" -"@babel/helper-module-imports@^7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.7.0.tgz#99c095889466e5f7b6d66d98dffc58baaf42654d" - integrity sha512-Dv3hLKIC1jyfTkClvyEkYP2OlkzNvWs5+Q8WgPbxM5LMeorons7iPP91JM+DU7tRbhqA1ZeooPaMFvQrn23RHw== +"@babel/helper-module-imports@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.7.4.tgz#e5a92529f8888bf319a6376abfbd1cebc491ad91" + integrity sha512-dGcrX6K9l8258WFjyDLJwuVKxR4XZfU0/vTUgOQYWEnRD8mgr+p4d6fCUMq/ys0h4CCt/S5JhbvtyErjWouAUQ== dependencies: - "@babel/types" "^7.7.0" + "@babel/types" "^7.7.4" -"@babel/helper-module-transforms@^7.1.0", "@babel/helper-module-transforms@^7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.7.0.tgz#154a69f0c5b8fd4d39e49750ff7ac4faa3f36786" - integrity sha512-rXEefBuheUYQyX4WjV19tuknrJFwyKw0HgzRwbkyTbB+Dshlq7eqkWbyjzToLrMZk/5wKVKdWFluiAsVkHXvuQ== +"@babel/helper-module-transforms@^7.7.4", "@babel/helper-module-transforms@^7.7.5": + version "7.7.5" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.7.5.tgz#d044da7ffd91ec967db25cd6748f704b6b244835" + integrity sha512-A7pSxyJf1gN5qXVcidwLWydjftUN878VkalhXX5iQDuGyiGK3sOrrKKHF4/A4fwHtnsotv/NipwAeLzY4KQPvw== dependencies: - "@babel/helper-module-imports" "^7.7.0" - "@babel/helper-simple-access" "^7.7.0" - "@babel/helper-split-export-declaration" "^7.7.0" - "@babel/template" "^7.7.0" - "@babel/types" "^7.7.0" + "@babel/helper-module-imports" "^7.7.4" + "@babel/helper-simple-access" "^7.7.4" + "@babel/helper-split-export-declaration" "^7.7.4" + "@babel/template" "^7.7.4" + "@babel/types" "^7.7.4" lodash "^4.17.13" -"@babel/helper-optimise-call-expression@^7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.7.0.tgz#4f66a216116a66164135dc618c5d8b7a959f9365" - integrity sha512-48TeqmbazjNU/65niiiJIJRc5JozB8acui1OS7bSd6PgxfuovWsvjfWSzlgx+gPFdVveNzUdpdIg5l56Pl5jqg== +"@babel/helper-optimise-call-expression@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.7.4.tgz#034af31370d2995242aa4df402c3b7794b2dcdf2" + integrity sha512-VB7gWZ2fDkSuqW6b1AKXkJWO5NyNI3bFL/kK79/30moK57blr6NbH8xcl2XcKCwOmJosftWunZqfO84IGq3ZZg== dependencies: - "@babel/types" "^7.7.0" + "@babel/types" "^7.7.4" "@babel/helper-plugin-utils@^7.0.0": version "7.0.0" @@ -176,60 +176,60 @@ dependencies: lodash "^4.17.13" -"@babel/helper-remap-async-to-generator@^7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.7.0.tgz#4d69ec653e8bff5bce62f5d33fc1508f223c75a7" - integrity sha512-pHx7RN8X0UNHPB/fnuDnRXVZ316ZigkO8y8D835JlZ2SSdFKb6yH9MIYRU4fy/KPe5sPHDFOPvf8QLdbAGGiyw== - dependencies: - "@babel/helper-annotate-as-pure" "^7.7.0" - "@babel/helper-wrap-function" "^7.7.0" - "@babel/template" "^7.7.0" - "@babel/traverse" "^7.7.0" - "@babel/types" "^7.7.0" - -"@babel/helper-replace-supers@^7.5.5", "@babel/helper-replace-supers@^7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.7.0.tgz#d5365c8667fe7cbd13b8ddddceb9bd7f2b387512" - integrity sha512-5ALYEul5V8xNdxEeWvRsBzLMxQksT7MaStpxjJf9KsnLxpAKBtfw5NeMKZJSYDa0lKdOcy0g+JT/f5mPSulUgg== - dependencies: - "@babel/helper-member-expression-to-functions" "^7.7.0" - "@babel/helper-optimise-call-expression" "^7.7.0" - "@babel/traverse" "^7.7.0" - "@babel/types" "^7.7.0" - -"@babel/helper-simple-access@^7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.7.0.tgz#97a8b6c52105d76031b86237dc1852b44837243d" - integrity sha512-AJ7IZD7Eem3zZRuj5JtzFAptBw7pMlS3y8Qv09vaBWoFsle0d1kAn5Wq6Q9MyBXITPOKnxwkZKoAm4bopmv26g== - dependencies: - "@babel/template" "^7.7.0" - "@babel/types" "^7.7.0" - -"@babel/helper-split-export-declaration@^7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.0.tgz#1365e74ea6c614deeb56ebffabd71006a0eb2300" - integrity sha512-HgYSI8rH08neWlAH3CcdkFg9qX9YsZysZI5GD8LjhQib/mM0jGOZOVkoUiiV2Hu978fRtjtsGsW6w0pKHUWtqA== - dependencies: - "@babel/types" "^7.7.0" - -"@babel/helper-wrap-function@^7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.7.0.tgz#15af3d3e98f8417a60554acbb6c14e75e0b33b74" - integrity sha512-sd4QjeMgQqzshSjecZjOp8uKfUtnpmCyQhKQrVJBBgeHAB/0FPi33h3AbVlVp07qQtMD4QgYSzaMI7VwncNK/w== - dependencies: - "@babel/helper-function-name" "^7.7.0" - "@babel/template" "^7.7.0" - "@babel/traverse" "^7.7.0" - "@babel/types" "^7.7.0" - -"@babel/helpers@^7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.7.0.tgz#359bb5ac3b4726f7c1fde0ec75f64b3f4275d60b" - integrity sha512-VnNwL4YOhbejHb7x/b5F39Zdg5vIQpUUNzJwx0ww1EcVRt41bbGRZWhAURrfY32T5zTT3qwNOQFWpn+P0i0a2g== - dependencies: - "@babel/template" "^7.7.0" - "@babel/traverse" "^7.7.0" - "@babel/types" "^7.7.0" +"@babel/helper-remap-async-to-generator@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.7.4.tgz#c68c2407350d9af0e061ed6726afb4fff16d0234" + integrity sha512-Sk4xmtVdM9sA/jCI80f+KS+Md+ZHIpjuqmYPk1M7F/upHou5e4ReYmExAiu6PVe65BhJPZA2CY9x9k4BqE5klw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.7.4" + "@babel/helper-wrap-function" "^7.7.4" + "@babel/template" "^7.7.4" + "@babel/traverse" "^7.7.4" + "@babel/types" "^7.7.4" + +"@babel/helper-replace-supers@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.7.4.tgz#3c881a6a6a7571275a72d82e6107126ec9e2cdd2" + integrity sha512-pP0tfgg9hsZWo5ZboYGuBn/bbYT/hdLPVSS4NMmiRJdwWhP0IznPwN9AE1JwyGsjSPLC364I0Qh5p+EPkGPNpg== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.7.4" + "@babel/helper-optimise-call-expression" "^7.7.4" + "@babel/traverse" "^7.7.4" + "@babel/types" "^7.7.4" + +"@babel/helper-simple-access@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.7.4.tgz#a169a0adb1b5f418cfc19f22586b2ebf58a9a294" + integrity sha512-zK7THeEXfan7UlWsG2A6CI/L9jVnI5+xxKZOdej39Y0YtDYKx9raHk5F2EtK9K8DHRTihYwg20ADt9S36GR78A== + dependencies: + "@babel/template" "^7.7.4" + "@babel/types" "^7.7.4" + +"@babel/helper-split-export-declaration@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz#57292af60443c4a3622cf74040ddc28e68336fd8" + integrity sha512-guAg1SXFcVr04Guk9eq0S4/rWS++sbmyqosJzVs8+1fH5NI+ZcmkaSkc7dmtAFbHFva6yRJnjW3yAcGxjueDug== + dependencies: + "@babel/types" "^7.7.4" + +"@babel/helper-wrap-function@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.7.4.tgz#37ab7fed5150e22d9d7266e830072c0cdd8baace" + integrity sha512-VsfzZt6wmsocOaVU0OokwrIytHND55yvyT4BPB9AIIgwr8+x7617hetdJTsuGwygN5RC6mxA9EJztTjuwm2ofg== + dependencies: + "@babel/helper-function-name" "^7.7.4" + "@babel/template" "^7.7.4" + "@babel/traverse" "^7.7.4" + "@babel/types" "^7.7.4" + +"@babel/helpers@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.7.4.tgz#62c215b9e6c712dadc15a9a0dcab76c92a940302" + integrity sha512-ak5NGZGJ6LV85Q1Zc9gn2n+ayXOizryhjSUBTdu5ih1tlVCJeuQENzc4ItyCVhINVXvIT/ZQ4mheGIsfBkpskg== + dependencies: + "@babel/template" "^7.7.4" + "@babel/traverse" "^7.7.4" + "@babel/types" "^7.7.4" "@babel/highlight@^7.0.0": version "7.5.0" @@ -240,478 +240,478 @@ esutils "^2.0.2" js-tokens "^4.0.0" -"@babel/parser@^7.0.0", "@babel/parser@^7.7.0", "@babel/parser@^7.7.2": - version "7.7.3" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.3.tgz#5fad457c2529de476a248f75b0f090b3060af043" - integrity sha512-bqv+iCo9i+uLVbI0ILzKkvMorqxouI+GbV13ivcARXn9NNEabi2IEz912IgNpT/60BNXac5dgcfjb94NjsF33A== +"@babel/parser@^7.0.0", "@babel/parser@^7.7.4", "@babel/parser@^7.7.7": + version "7.7.7" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.7.tgz#1b886595419cf92d811316d5b715a53ff38b4937" + integrity sha512-WtTZMZAZLbeymhkd/sEaPD8IQyGAhmuTuvTzLiCFM7iXiVdY0gc0IaI+cW0fh1BnSMbJSzXX6/fHllgHKwHhXw== -"@babel/plugin-proposal-async-generator-functions@^7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.7.0.tgz#83ef2d6044496b4c15d8b4904e2219e6dccc6971" - integrity sha512-ot/EZVvf3mXtZq0Pd0+tSOfGWMizqmOohXmNZg6LNFjHOV+wOPv7BvVYh8oPR8LhpIP3ye8nNooKL50YRWxpYA== +"@babel/plugin-proposal-async-generator-functions@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.7.4.tgz#0351c5ac0a9e927845fffd5b82af476947b7ce6d" + integrity sha512-1ypyZvGRXriY/QP668+s8sFr2mqinhkRDMPSQLNghCQE+GAkFtp+wkHVvg2+Hdki8gwP+NFzJBJ/N1BfzCCDEw== dependencies: "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-remap-async-to-generator" "^7.7.0" - "@babel/plugin-syntax-async-generators" "^7.2.0" + "@babel/helper-remap-async-to-generator" "^7.7.4" + "@babel/plugin-syntax-async-generators" "^7.7.4" -"@babel/plugin-proposal-dynamic-import@^7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.7.0.tgz#dc02a8bad8d653fb59daf085516fa416edd2aa7f" - integrity sha512-7poL3Xi+QFPC7sGAzEIbXUyYzGJwbc2+gSD0AkiC5k52kH2cqHdqxm5hNFfLW3cRSTcx9bN0Fl7/6zWcLLnKAQ== +"@babel/plugin-proposal-dynamic-import@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.7.4.tgz#dde64a7f127691758cbfed6cf70de0fa5879d52d" + integrity sha512-StH+nGAdO6qDB1l8sZ5UBV8AC3F2VW2I8Vfld73TMKyptMU9DY5YsJAS8U81+vEtxcH3Y/La0wG0btDrhpnhjQ== dependencies: "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-dynamic-import" "^7.2.0" + "@babel/plugin-syntax-dynamic-import" "^7.7.4" -"@babel/plugin-proposal-json-strings@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz#568ecc446c6148ae6b267f02551130891e29f317" - integrity sha512-MAFV1CA/YVmYwZG0fBQyXhmj0BHCB5egZHCKWIFVv/XCxAeVGIHfos3SwDck4LvCllENIAg7xMKOG5kH0dzyUg== +"@babel/plugin-proposal-json-strings@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.7.4.tgz#7700a6bfda771d8dc81973249eac416c6b4c697d" + integrity sha512-wQvt3akcBTfLU/wYoqm/ws7YOAQKu8EVJEvHip/mzkNtjaclQoCCIqKXFP5/eyfnfbQCDV3OLRIK3mIVyXuZlw== dependencies: "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-json-strings" "^7.2.0" + "@babel/plugin-syntax-json-strings" "^7.7.4" -"@babel/plugin-proposal-object-rest-spread@^7.6.2": - version "7.6.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.6.2.tgz#8ffccc8f3a6545e9f78988b6bf4fe881b88e8096" - integrity sha512-LDBXlmADCsMZV1Y9OQwMc0MyGZ8Ta/zlD9N67BfQT8uYwkRswiu2hU6nJKrjrt/58aH/vqfQlR/9yId/7A2gWw== +"@babel/plugin-proposal-object-rest-spread@^7.7.7": + version "7.7.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.7.7.tgz#9f27075004ab99be08c5c1bd653a2985813cb370" + integrity sha512-3qp9I8lelgzNedI3hrhkvhaEYree6+WHnyA/q4Dza9z7iEIs1eyhWyJnetk3jJ69RT0AT4G0UhEGwyGFJ7GUuQ== dependencies: "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-object-rest-spread" "^7.2.0" + "@babel/plugin-syntax-object-rest-spread" "^7.7.4" -"@babel/plugin-proposal-optional-catch-binding@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz#135d81edb68a081e55e56ec48541ece8065c38f5" - integrity sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g== +"@babel/plugin-proposal-optional-catch-binding@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.7.4.tgz#ec21e8aeb09ec6711bc0a39ca49520abee1de379" + integrity sha512-DyM7U2bnsQerCQ+sejcTNZh8KQEUuC3ufzdnVnSiUv/qoGJp2Z3hanKL18KDhsBT5Wj6a7CMT5mdyCNJsEaA9w== dependencies: "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-optional-catch-binding" "^7.2.0" + "@babel/plugin-syntax-optional-catch-binding" "^7.7.4" -"@babel/plugin-proposal-unicode-property-regex@^7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.7.0.tgz#549fe1717a1bd0a2a7e63163841cb37e78179d5d" - integrity sha512-mk34H+hp7kRBWJOOAR0ZMGCydgKMD4iN9TpDRp3IIcbunltxEY89XSimc6WbtSLCDrwcdy/EEw7h5CFCzxTchw== +"@babel/plugin-proposal-unicode-property-regex@^7.7.7": + version "7.7.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.7.7.tgz#433fa9dac64f953c12578b29633f456b68831c4e" + integrity sha512-80PbkKyORBUVm1fbTLrHpYdJxMThzM1UqFGh0ALEhO9TYbG86Ah9zQYAB/84axz2vcxefDLdZwWwZNlYARlu9w== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.7.0" + "@babel/helper-create-regexp-features-plugin" "^7.7.4" "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-syntax-async-generators@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz#69e1f0db34c6f5a0cf7e2b3323bf159a76c8cb7f" - integrity sha512-1ZrIRBv2t0GSlcwVoQ6VgSLpLgiN/FVQUzt9znxo7v2Ov4jJrs8RY8tv0wvDmFN3qIdMKWrmMMW6yZ0G19MfGg== +"@babel/plugin-syntax-async-generators@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.7.4.tgz#331aaf310a10c80c44a66b238b6e49132bd3c889" + integrity sha512-Li4+EjSpBgxcsmeEF8IFcfV/+yJGxHXDirDkEoyFjumuwbmfCVHUt0HuowD/iGM7OhIRyXJH9YXxqiH6N815+g== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-syntax-dynamic-import@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.2.0.tgz#69c159ffaf4998122161ad8ebc5e6d1f55df8612" - integrity sha512-mVxuJ0YroI/h/tbFTPGZR8cv6ai+STMKNBq0f8hFxsxWjl94qqhsb+wXbpNMDPU3cfR1TIsVFzU3nXyZMqyK4w== +"@babel/plugin-syntax-dynamic-import@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.7.4.tgz#29ca3b4415abfe4a5ec381e903862ad1a54c3aec" + integrity sha512-jHQW0vbRGvwQNgyVxwDh4yuXu4bH1f5/EICJLAhl1SblLs2CDhrsmCk+v5XLdE9wxtAFRyxx+P//Iw+a5L/tTg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-syntax-flow@^7.2.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.7.0.tgz#5c9465bcd26354d5215294ea90ab1c706a571386" - integrity sha512-vQMV07p+L+jZeUnvX3pEJ9EiXGCjB5CTTvsirFD9rpEuATnoAvLBLoYbw1v5tyn3d2XxSuvEKi8cV3KqYUa0vQ== +"@babel/plugin-syntax-flow@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.7.4.tgz#6d91b59e1a0e4c17f36af2e10dd64ef220919d7b" + integrity sha512-2AMAWl5PsmM5KPkB22cvOkUyWk6MjUaqhHNU5nSPUl/ns3j5qLfw2SuYP5RbVZ0tfLvePr4zUScbICtDP2CUNw== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-syntax-json-strings@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz#72bd13f6ffe1d25938129d2a186b11fd62951470" - integrity sha512-5UGYnMSLRE1dqqZwug+1LISpA403HzlSfsg6P9VXU6TBjcSHeNlw4DxDx7LgpF+iKZoOG/+uzqoRHTdcUpiZNg== +"@babel/plugin-syntax-json-strings@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.7.4.tgz#86e63f7d2e22f9e27129ac4e83ea989a382e86cc" + integrity sha512-QpGupahTQW1mHRXddMG5srgpHWqRLwJnJZKXTigB9RPFCCGbDGCgBeM/iC82ICXp414WeYx/tD54w7M2qRqTMg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-syntax-jsx@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.2.0.tgz#0b85a3b4bc7cdf4cc4b8bf236335b907ca22e7c7" - integrity sha512-VyN4QANJkRW6lDBmENzRszvZf3/4AXaj9YR7GwrWeeN9tEBPuXbmDYVU9bYBN0D70zCWVwUy0HWq2553VCb6Hw== +"@babel/plugin-syntax-jsx@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.7.4.tgz#dab2b56a36fb6c3c222a1fbc71f7bf97f327a9ec" + integrity sha512-wuy6fiMe9y7HeZBWXYCGt2RGxZOj0BImZ9EyXJVnVGBKO/Br592rbR3rtIQn0eQhAk9vqaKP5n8tVqEFBQMfLg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-syntax-object-rest-spread@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz#3b7a3e733510c57e820b9142a6579ac8b0dfad2e" - integrity sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA== +"@babel/plugin-syntax-object-rest-spread@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.7.4.tgz#47cf220d19d6d0d7b154304701f468fc1cc6ff46" + integrity sha512-mObR+r+KZq0XhRVS2BrBKBpr5jqrqzlPvS9C9vuOf5ilSwzloAl7RPWLrgKdWS6IreaVrjHxTjtyqFiOisaCwg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-syntax-optional-catch-binding@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz#a94013d6eda8908dfe6a477e7f9eda85656ecf5c" - integrity sha512-bDe4xKNhb0LI7IvZHiA13kff0KEfaGX/Hv4lMA9+7TEc63hMNvfKo6ZFpXhKuEp+II/q35Gc4NoMeDZyaUbj9w== +"@babel/plugin-syntax-optional-catch-binding@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.7.4.tgz#a3e38f59f4b6233867b4a92dcb0ee05b2c334aa6" + integrity sha512-4ZSuzWgFxqHRE31Glu+fEr/MirNZOMYmD/0BhBWyLyOOQz/gTAl7QmWm2hX1QxEIXsr2vkdlwxIzTyiYRC4xcQ== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-syntax-top-level-await@^7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.7.0.tgz#f5699549f50bbe8d12b1843a4e82f0a37bb65f4d" - integrity sha512-hi8FUNiFIY1fnUI2n1ViB1DR0R4QeK4iHcTlW6aJkrPoTdb8Rf1EMQ6GT3f67DDkYyWgew9DFoOZ6gOoEsdzTA== +"@babel/plugin-syntax-top-level-await@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.7.4.tgz#bd7d8fa7b9fee793a36e4027fd6dd1aa32f946da" + integrity sha512-wdsOw0MvkL1UIgiQ/IFr3ETcfv1xb8RMM0H9wbiDyLaJFyiDg5oZvDLCXosIXmFeIlweML5iOBXAkqddkYNizg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-syntax-typescript@^7.2.0": - version "7.3.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.3.3.tgz#a7cc3f66119a9f7ebe2de5383cce193473d65991" - integrity sha512-dGwbSMA1YhVS8+31CnPR7LB4pcbrzcV99wQzby4uAfrkZPYZlQ7ImwdpzLqi6Z6IL02b8IAL379CaMwo0x5Lag== +"@babel/plugin-syntax-typescript@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.7.4.tgz#5d037ffa10f3b25a16f32570ebbe7a8c2efa304b" + integrity sha512-77blgY18Hud4NM1ggTA8xVT/dBENQf17OpiToSa2jSmEY3fWXD2jwrdVlO4kq5yzUTeF15WSQ6b4fByNvJcjpQ== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-arrow-functions@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz#9aeafbe4d6ffc6563bf8f8372091628f00779550" - integrity sha512-ER77Cax1+8/8jCB9fo4Ud161OZzWN5qawi4GusDuRLcDbDG+bIGYY20zb2dfAFdTRGzrfq2xZPvF0R64EHnimg== +"@babel/plugin-transform-arrow-functions@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.7.4.tgz#76309bd578addd8aee3b379d809c802305a98a12" + integrity sha512-zUXy3e8jBNPiffmqkHRNDdZM2r8DWhCB7HhcoyZjiK1TxYEluLHAvQuYnTT+ARqRpabWqy/NHkO6e3MsYB5YfA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-async-to-generator@^7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.7.0.tgz#e2b84f11952cf5913fe3438b7d2585042772f492" - integrity sha512-vLI2EFLVvRBL3d8roAMqtVY0Bm9C1QzLkdS57hiKrjUBSqsQYrBsMCeOg/0KK7B0eK9V71J5mWcha9yyoI2tZw== +"@babel/plugin-transform-async-to-generator@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.7.4.tgz#694cbeae6d613a34ef0292713fa42fb45c4470ba" + integrity sha512-zpUTZphp5nHokuy8yLlyafxCJ0rSlFoSHypTUWgpdwoDXWQcseaect7cJ8Ppk6nunOM6+5rPMkod4OYKPR5MUg== dependencies: - "@babel/helper-module-imports" "^7.7.0" + "@babel/helper-module-imports" "^7.7.4" "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-remap-async-to-generator" "^7.7.0" + "@babel/helper-remap-async-to-generator" "^7.7.4" -"@babel/plugin-transform-block-scoped-functions@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz#5d3cc11e8d5ddd752aa64c9148d0db6cb79fd190" - integrity sha512-ntQPR6q1/NKuphly49+QiQiTN0O63uOwjdD6dhIjSWBI5xlrbUFh720TIpzBhpnrLfv2tNH/BXvLIab1+BAI0w== +"@babel/plugin-transform-block-scoped-functions@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.7.4.tgz#d0d9d5c269c78eaea76227ace214b8d01e4d837b" + integrity sha512-kqtQzwtKcpPclHYjLK//3lH8OFsCDuDJBaFhVwf8kqdnF6MN4l618UDlcA7TfRs3FayrHj+svYnSX8MC9zmUyQ== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-block-scoping@^7.6.3": - version "7.6.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.6.3.tgz#6e854e51fbbaa84351b15d4ddafe342f3a5d542a" - integrity sha512-7hvrg75dubcO3ZI2rjYTzUrEuh1E9IyDEhhB6qfcooxhDA33xx2MasuLVgdxzcP6R/lipAC6n9ub9maNW6RKdw== +"@babel/plugin-transform-block-scoping@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.7.4.tgz#200aad0dcd6bb80372f94d9e628ea062c58bf224" + integrity sha512-2VBe9u0G+fDt9B5OV5DQH4KBf5DoiNkwFKOz0TCvBWvdAN2rOykCTkrL+jTLxfCAm76l9Qo5OqL7HBOx2dWggg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" lodash "^4.17.13" -"@babel/plugin-transform-classes@^7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.7.0.tgz#b411ecc1b8822d24b81e5d184f24149136eddd4a" - integrity sha512-/b3cKIZwGeUesZheU9jNYcwrEA7f/Bo4IdPmvp7oHgvks2majB5BoT5byAql44fiNQYOPzhk2w8DbgfuafkMoA== +"@babel/plugin-transform-classes@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.7.4.tgz#c92c14be0a1399e15df72667067a8f510c9400ec" + integrity sha512-sK1mjWat7K+buWRuImEzjNf68qrKcrddtpQo3swi9j7dUcG6y6R6+Di039QN2bD1dykeswlagupEmpOatFHHUg== dependencies: - "@babel/helper-annotate-as-pure" "^7.7.0" - "@babel/helper-define-map" "^7.7.0" - "@babel/helper-function-name" "^7.7.0" - "@babel/helper-optimise-call-expression" "^7.7.0" + "@babel/helper-annotate-as-pure" "^7.7.4" + "@babel/helper-define-map" "^7.7.4" + "@babel/helper-function-name" "^7.7.4" + "@babel/helper-optimise-call-expression" "^7.7.4" "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-replace-supers" "^7.7.0" - "@babel/helper-split-export-declaration" "^7.7.0" + "@babel/helper-replace-supers" "^7.7.4" + "@babel/helper-split-export-declaration" "^7.7.4" globals "^11.1.0" -"@babel/plugin-transform-computed-properties@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz#83a7df6a658865b1c8f641d510c6f3af220216da" - integrity sha512-kP/drqTxY6Xt3NNpKiMomfgkNn4o7+vKxK2DDKcBG9sHj51vHqMBGy8wbDS/J4lMxnqs153/T3+DmCEAkC5cpA== +"@babel/plugin-transform-computed-properties@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.7.4.tgz#e856c1628d3238ffe12d668eb42559f79a81910d" + integrity sha512-bSNsOsZnlpLLyQew35rl4Fma3yKWqK3ImWMSC/Nc+6nGjC9s5NFWAer1YQ899/6s9HxO2zQC1WoFNfkOqRkqRQ== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-destructuring@^7.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.6.0.tgz#44bbe08b57f4480094d57d9ffbcd96d309075ba6" - integrity sha512-2bGIS5P1v4+sWTCnKNDZDxbGvEqi0ijeqM/YqHtVGrvG2y0ySgnEEhXErvE9dA0bnIzY9bIzdFK0jFA46ASIIQ== +"@babel/plugin-transform-destructuring@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.7.4.tgz#2b713729e5054a1135097b6a67da1b6fe8789267" + integrity sha512-4jFMXI1Cu2aXbcXXl8Lr6YubCn6Oc7k9lLsu8v61TZh+1jny2BWmdtvY9zSUlLdGUvcy9DMAWyZEOqjsbeg/wA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-dotall-regex@^7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.7.0.tgz#c5c9ecacab3a5e0c11db6981610f0c32fd698b3b" - integrity sha512-3QQlF7hSBnSuM1hQ0pS3pmAbWLax/uGNCbPBND9y+oJ4Y776jsyujG2k0Sn2Aj2a0QwVOiOFL5QVPA7spjvzSA== +"@babel/plugin-transform-dotall-regex@^7.7.7": + version "7.7.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.7.7.tgz#3e9713f1b69f339e87fa796b097d73ded16b937b" + integrity sha512-b4in+YlTeE/QmTgrllnb3bHA0HntYvjz8O3Mcbx75UBPJA2xhb5A8nle498VhxSXJHQefjtQxpnLPehDJ4TRlg== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.7.0" + "@babel/helper-create-regexp-features-plugin" "^7.7.4" "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-duplicate-keys@^7.5.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.5.0.tgz#c5dbf5106bf84cdf691222c0974c12b1df931853" - integrity sha512-igcziksHizyQPlX9gfSjHkE2wmoCH3evvD2qR5w29/Dk0SMKE/eOI7f1HhBdNhR/zxJDqrgpoDTq5YSLH/XMsQ== +"@babel/plugin-transform-duplicate-keys@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.7.4.tgz#3d21731a42e3f598a73835299dd0169c3b90ac91" + integrity sha512-g1y4/G6xGWMD85Tlft5XedGaZBCIVN+/P0bs6eabmcPP9egFleMAo65OOjlhcz1njpwagyY3t0nsQC9oTFegJA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-exponentiation-operator@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz#a63868289e5b4007f7054d46491af51435766008" - integrity sha512-umh4hR6N7mu4Elq9GG8TOu9M0bakvlsREEC+ialrQN6ABS4oDQ69qJv1VtR3uxlKMCQMCvzk7vr17RHKcjx68A== +"@babel/plugin-transform-exponentiation-operator@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.7.4.tgz#dd30c0191e3a1ba19bcc7e389bdfddc0729d5db9" + integrity sha512-MCqiLfCKm6KEA1dglf6Uqq1ElDIZwFuzz1WH5mTf8k2uQSxEJMbOIEh7IZv7uichr7PMfi5YVSrr1vz+ipp7AQ== dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.1.0" + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.7.4" "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-flow-strip-types@^7.0.0": - version "7.6.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.6.3.tgz#8110f153e7360cfd5996eee68706cfad92d85256" - integrity sha512-l0ETkyEofkqFJ9LS6HChNIKtVJw2ylKbhYMlJ5C6df+ldxxaLIyXY4yOdDQQspfFpV8/vDiaWoJlvflstlYNxg== + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.7.4.tgz#cc73f85944782df1d77d80977bc097920a8bf31a" + integrity sha512-w9dRNlHY5ElNimyMYy0oQowvQpwt/PRHI0QS98ZJCTZU2bvSnKXo5zEiD5u76FBPigTm8TkqzmnUTg16T7qbkA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-flow" "^7.2.0" + "@babel/plugin-syntax-flow" "^7.7.4" -"@babel/plugin-transform-for-of@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.4.tgz#0267fc735e24c808ba173866c6c4d1440fc3c556" - integrity sha512-9T/5Dlr14Z9TIEXLXkt8T1DU7F24cbhwhMNUziN3hB1AXoZcdzPcTiKGRn/6iOymDqtTKWnr/BtRKN9JwbKtdQ== +"@babel/plugin-transform-for-of@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.7.4.tgz#248800e3a5e507b1f103d8b4ca998e77c63932bc" + integrity sha512-zZ1fD1B8keYtEcKF+M1TROfeHTKnijcVQm0yO/Yu1f7qoDoxEIc/+GX6Go430Bg84eM/xwPFp0+h4EbZg7epAA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-function-name@^7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.7.0.tgz#0fa786f1eef52e3b7d4fc02e54b2129de8a04c2a" - integrity sha512-P5HKu0d9+CzZxP5jcrWdpe7ZlFDe24bmqP6a6X8BHEBl/eizAsY8K6LX8LASZL0Jxdjm5eEfzp+FIrxCm/p8bA== +"@babel/plugin-transform-function-name@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.7.4.tgz#75a6d3303d50db638ff8b5385d12451c865025b1" + integrity sha512-E/x09TvjHNhsULs2IusN+aJNRV5zKwxu1cpirZyRPw+FyyIKEHPXTsadj48bVpc1R5Qq1B5ZkzumuFLytnbT6g== dependencies: - "@babel/helper-function-name" "^7.7.0" + "@babel/helper-function-name" "^7.7.4" "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-literals@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz#690353e81f9267dad4fd8cfd77eafa86aba53ea1" - integrity sha512-2ThDhm4lI4oV7fVQ6pNNK+sx+c/GM5/SaML0w/r4ZB7sAneD/piDJtwdKlNckXeyGK7wlwg2E2w33C/Hh+VFCg== +"@babel/plugin-transform-literals@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.7.4.tgz#27fe87d2b5017a2a5a34d1c41a6b9f6a6262643e" + integrity sha512-X2MSV7LfJFm4aZfxd0yLVFrEXAgPqYoDG53Br/tCKiKYfX0MjVjQeWPIhPHHsCqzwQANq+FLN786fF5rgLS+gw== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-member-expression-literals@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.2.0.tgz#fa10aa5c58a2cb6afcf2c9ffa8cb4d8b3d489a2d" - integrity sha512-HiU3zKkSU6scTidmnFJ0bMX8hz5ixC93b4MHMiYebmk2lUVNGOboPsqQvx5LzooihijUoLR/v7Nc1rbBtnc7FA== +"@babel/plugin-transform-member-expression-literals@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.7.4.tgz#aee127f2f3339fc34ce5e3055d7ffbf7aa26f19a" + integrity sha512-9VMwMO7i69LHTesL0RdGy93JU6a+qOPuvB4F4d0kR0zyVjJRVJRaoaGjhtki6SzQUu8yen/vxPKN6CWnCUw6bA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-modules-amd@^7.5.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.5.0.tgz#ef00435d46da0a5961aa728a1d2ecff063e4fb91" - integrity sha512-n20UsQMKnWrltocZZm24cRURxQnWIvsABPJlw/fvoy9c6AgHZzoelAIzajDHAQrDpuKFFPPcFGd7ChsYuIUMpg== +"@babel/plugin-transform-modules-amd@^7.7.5": + version "7.7.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.7.5.tgz#39e0fb717224b59475b306402bb8eedab01e729c" + integrity sha512-CT57FG4A2ZUNU1v+HdvDSDrjNWBrtCmSH6YbbgN3Lrf0Di/q/lWRxZrE72p3+HCCz9UjfZOEBdphgC0nzOS6DQ== dependencies: - "@babel/helper-module-transforms" "^7.1.0" + "@babel/helper-module-transforms" "^7.7.5" "@babel/helper-plugin-utils" "^7.0.0" babel-plugin-dynamic-import-node "^2.3.0" -"@babel/plugin-transform-modules-commonjs@^7.0.0", "@babel/plugin-transform-modules-commonjs@^7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.7.0.tgz#3e5ffb4fd8c947feede69cbe24c9554ab4113fe3" - integrity sha512-KEMyWNNWnjOom8vR/1+d+Ocz/mILZG/eyHHO06OuBQ2aNhxT62fr4y6fGOplRx+CxCSp3IFwesL8WdINfY/3kg== +"@babel/plugin-transform-modules-commonjs@^7.0.0", "@babel/plugin-transform-modules-commonjs@^7.7.5": + version "7.7.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.7.5.tgz#1d27f5eb0bcf7543e774950e5b2fa782e637b345" + integrity sha512-9Cq4zTFExwFhQI6MT1aFxgqhIsMWQWDVwOgLzl7PTWJHsNaqFvklAU+Oz6AQLAS0dJKTwZSOCo20INwktxpi3Q== dependencies: - "@babel/helper-module-transforms" "^7.7.0" + "@babel/helper-module-transforms" "^7.7.5" "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-simple-access" "^7.7.0" + "@babel/helper-simple-access" "^7.7.4" babel-plugin-dynamic-import-node "^2.3.0" -"@babel/plugin-transform-modules-systemjs@^7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.7.0.tgz#9baf471213af9761c1617bb12fd278e629041417" - integrity sha512-ZAuFgYjJzDNv77AjXRqzQGlQl4HdUM6j296ee4fwKVZfhDR9LAGxfvXjBkb06gNETPnN0sLqRm9Gxg4wZH6dXg== +"@babel/plugin-transform-modules-systemjs@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.7.4.tgz#cd98152339d3e763dfe838b7d4273edaf520bb30" + integrity sha512-y2c96hmcsUi6LrMqvmNDPBBiGCiQu0aYqpHatVVu6kD4mFEXKjyNxd/drc18XXAf9dv7UXjrZwBVmTTGaGP8iw== dependencies: - "@babel/helper-hoist-variables" "^7.7.0" + "@babel/helper-hoist-variables" "^7.7.4" "@babel/helper-plugin-utils" "^7.0.0" babel-plugin-dynamic-import-node "^2.3.0" -"@babel/plugin-transform-modules-umd@^7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.7.0.tgz#d62c7da16670908e1d8c68ca0b5d4c0097b69966" - integrity sha512-u7eBA03zmUswQ9LQ7Qw0/ieC1pcAkbp5OQatbWUzY1PaBccvuJXUkYzoN1g7cqp7dbTu6Dp9bXyalBvD04AANA== +"@babel/plugin-transform-modules-umd@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.7.4.tgz#1027c355a118de0aae9fee00ad7813c584d9061f" + integrity sha512-u2B8TIi0qZI4j8q4C51ktfO7E3cQ0qnaXFI1/OXITordD40tt17g/sXqgNNCcMTcBFKrUPcGDx+TBJuZxLx7tw== dependencies: - "@babel/helper-module-transforms" "^7.7.0" + "@babel/helper-module-transforms" "^7.7.4" "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-named-capturing-groups-regex@^7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.7.0.tgz#358e6fd869b9a4d8f5cbc79e4ed4fc340e60dcaf" - integrity sha512-+SicSJoKouPctL+j1pqktRVCgy+xAch1hWWTMy13j0IflnyNjaoskj+DwRQFimHbLqO3sq2oN2CXMvXq3Bgapg== +"@babel/plugin-transform-named-capturing-groups-regex@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.7.4.tgz#fb3bcc4ee4198e7385805007373d6b6f42c98220" + integrity sha512-jBUkiqLKvUWpv9GLSuHUFYdmHg0ujC1JEYoZUfeOOfNydZXp1sXObgyPatpcwjWgsdBGsagWW0cdJpX/DO2jMw== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.7.0" + "@babel/helper-create-regexp-features-plugin" "^7.7.4" -"@babel/plugin-transform-new-target@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.4.4.tgz#18d120438b0cc9ee95a47f2c72bc9768fbed60a5" - integrity sha512-r1z3T2DNGQwwe2vPGZMBNjioT2scgWzK9BCnDEh+46z8EEwXBq24uRzd65I7pjtugzPSj921aM15RpESgzsSuA== +"@babel/plugin-transform-new-target@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.7.4.tgz#4a0753d2d60639437be07b592a9e58ee00720167" + integrity sha512-CnPRiNtOG1vRodnsyGX37bHQleHE14B9dnnlgSeEs3ek3fHN1A1SScglTCg1sfbe7sRQ2BUcpgpTpWSfMKz3gg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-object-super@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.5.5.tgz#c70021df834073c65eb613b8679cc4a381d1a9f9" - integrity sha512-un1zJQAhSosGFBduPgN/YFNvWVpRuHKU7IHBglLoLZsGmruJPOo6pbInneflUdmq7YvSVqhpPs5zdBvLnteltQ== +"@babel/plugin-transform-object-super@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.7.4.tgz#48488937a2d586c0148451bf51af9d7dda567262" + integrity sha512-ho+dAEhC2aRnff2JCA0SAK7V2R62zJd/7dmtoe7MHcso4C2mS+vZjn1Pb1pCVZvJs1mgsvv5+7sT+m3Bysb6eg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-replace-supers" "^7.5.5" + "@babel/helper-replace-supers" "^7.7.4" -"@babel/plugin-transform-parameters@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.4.tgz#7556cf03f318bd2719fe4c922d2d808be5571e16" - integrity sha512-oMh5DUO1V63nZcu/ZVLQFqiihBGo4OpxJxR1otF50GMeCLiRx5nUdtokd+u9SuVJrvvuIh9OosRFPP4pIPnwmw== +"@babel/plugin-transform-parameters@^7.7.7": + version "7.7.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.7.7.tgz#7a884b2460164dc5f194f668332736584c760007" + integrity sha512-OhGSrf9ZBrr1fw84oFXj5hgi8Nmg+E2w5L7NhnG0lPvpDtqd7dbyilM2/vR8CKbJ907RyxPh2kj6sBCSSfI9Ew== dependencies: - "@babel/helper-call-delegate" "^7.4.4" - "@babel/helper-get-function-arity" "^7.0.0" + "@babel/helper-call-delegate" "^7.7.4" + "@babel/helper-get-function-arity" "^7.7.4" "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-property-literals@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.2.0.tgz#03e33f653f5b25c4eb572c98b9485055b389e905" - integrity sha512-9q7Dbk4RhgcLp8ebduOpCbtjh7C0itoLYHXd9ueASKAG/is5PQtMR5VJGka9NKqGhYEGn5ITahd4h9QeBMylWQ== +"@babel/plugin-transform-property-literals@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.7.4.tgz#2388d6505ef89b266103f450f9167e6bd73f98c2" + integrity sha512-MatJhlC4iHsIskWYyawl53KuHrt+kALSADLQQ/HkhTjX954fkxIEh4q5slL4oRAnsm/eDoZ4q0CIZpcqBuxhJQ== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-react-jsx@^7.0.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.7.0.tgz#834b0723ba78cd4d24d7d629300c2270f516d0b7" - integrity sha512-mXhBtyVB1Ujfy+0L6934jeJcSXj/VCg6whZzEcgiiZHNS0PGC7vUCsZDQCxxztkpIdF+dY1fUMcjAgEOC3ZOMQ== + version "7.7.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.7.7.tgz#5cbaa7445b4a09f774029f3cc7bb448ff3122a5d" + integrity sha512-SlPjWPbva2+7/ZJbGcoqjl4LsQaLpKEzxW9hcxU7675s24JmdotJOSJ4cgAbV82W3FcZpHIGmRZIlUL8ayMvjw== dependencies: - "@babel/helper-builder-react-jsx" "^7.7.0" + "@babel/helper-builder-react-jsx" "^7.7.4" "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-jsx" "^7.2.0" + "@babel/plugin-syntax-jsx" "^7.7.4" -"@babel/plugin-transform-regenerator@^7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.7.0.tgz#f1b20b535e7716b622c99e989259d7dd942dd9cc" - integrity sha512-AXmvnC+0wuj/cFkkS/HFHIojxH3ffSXE+ttulrqWjZZRaUOonfJc60e1wSNT4rV8tIunvu/R3wCp71/tLAa9xg== +"@babel/plugin-transform-regenerator@^7.7.5": + version "7.7.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.7.5.tgz#3a8757ee1a2780f390e89f246065ecf59c26fce9" + integrity sha512-/8I8tPvX2FkuEyWbjRCt4qTAgZK0DVy8QRguhA524UH48RfGJy94On2ri+dCuwOpcerPRl9O4ebQkRcVzIaGBw== dependencies: regenerator-transform "^0.14.0" -"@babel/plugin-transform-reserved-words@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.2.0.tgz#4792af87c998a49367597d07fedf02636d2e1634" - integrity sha512-fz43fqW8E1tAB3DKF19/vxbpib1fuyCwSPE418ge5ZxILnBhWyhtPgz8eh1RCGGJlwvksHkyxMxh0eenFi+kFw== +"@babel/plugin-transform-reserved-words@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.7.4.tgz#6a7cf123ad175bb5c69aec8f6f0770387ed3f1eb" + integrity sha512-OrPiUB5s5XvkCO1lS7D8ZtHcswIC57j62acAnJZKqGGnHP+TIc/ljQSrgdX/QyOTdEK5COAhuc820Hi1q2UgLQ== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-shorthand-properties@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz#6333aee2f8d6ee7e28615457298934a3b46198f0" - integrity sha512-QP4eUM83ha9zmYtpbnyjTLAGKQritA5XW/iG9cjtuOI8s1RuL/3V6a3DeSHfKutJQ+ayUfeZJPcnCYEQzaPQqg== +"@babel/plugin-transform-shorthand-properties@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.7.4.tgz#74a0a9b2f6d67a684c6fbfd5f0458eb7ba99891e" + integrity sha512-q+suddWRfIcnyG5YiDP58sT65AJDZSUhXQDZE3r04AuqD6d/XLaQPPXSBzP2zGerkgBivqtQm9XKGLuHqBID6Q== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-spread@^7.6.2": - version "7.6.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.6.2.tgz#fc77cf798b24b10c46e1b51b1b88c2bf661bb8dd" - integrity sha512-DpSvPFryKdK1x+EDJYCy28nmAaIMdxmhot62jAXF/o99iA33Zj2Lmcp3vDmz+MUh0LNYVPvfj5iC3feb3/+PFg== +"@babel/plugin-transform-spread@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.7.4.tgz#aa673b356fe6b7e70d69b6e33a17fef641008578" + integrity sha512-8OSs0FLe5/80cndziPlg4R0K6HcWSM0zyNhHhLsmw/Nc5MaA49cAsnoJ/t/YZf8qkG7fD+UjTRaApVDB526d7Q== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-sticky-regex@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz#a1e454b5995560a9c1e0d537dfc15061fd2687e1" - integrity sha512-KKYCoGaRAf+ckH8gEL3JHUaFVyNHKe3ASNsZ+AlktgHevvxGigoIttrEJb8iKN03Q7Eazlv1s6cx2B2cQ3Jabw== +"@babel/plugin-transform-sticky-regex@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.7.4.tgz#ffb68c05090c30732076b1285dc1401b404a123c" + integrity sha512-Ls2NASyL6qtVe1H1hXts9yuEeONV2TJZmplLONkMPUG158CtmnrzW5Q5teibM5UVOFjG0D3IC5mzXR6pPpUY7A== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-regex" "^7.0.0" -"@babel/plugin-transform-template-literals@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.4.4.tgz#9d28fea7bbce637fb7612a0750989d8321d4bcb0" - integrity sha512-mQrEC4TWkhLN0z8ygIvEL9ZEToPhG5K7KDW3pzGqOfIGZ28Jb0POUkeWcoz8HnHvhFy6dwAT1j8OzqN8s804+g== +"@babel/plugin-transform-template-literals@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.7.4.tgz#1eb6411736dd3fe87dbd20cc6668e5121c17d604" + integrity sha512-sA+KxLwF3QwGj5abMHkHgshp9+rRz+oY9uoRil4CyLtgEuE/88dpkeWgNk5qKVsJE9iSfly3nvHapdRiIS2wnQ== dependencies: - "@babel/helper-annotate-as-pure" "^7.0.0" + "@babel/helper-annotate-as-pure" "^7.7.4" "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-typeof-symbol@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.2.0.tgz#117d2bcec2fbf64b4b59d1f9819894682d29f2b2" - integrity sha512-2LNhETWYxiYysBtrBTqL8+La0jIoQQnIScUJc74OYvUGRmkskNY4EzLCnjHBzdmb38wqtTaixpo1NctEcvMDZw== +"@babel/plugin-transform-typeof-symbol@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.7.4.tgz#3174626214f2d6de322882e498a38e8371b2140e" + integrity sha512-KQPUQ/7mqe2m0B8VecdyaW5XcQYaePyl9R7IsKd+irzj6jvbhoGnRE+M0aNkyAzI07VfUQ9266L5xMARitV3wg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-typescript@^7.4.5": - version "7.7.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.7.2.tgz#eb9f14c516b5d36f4d6f3a9d7badae6d0fc313d4" - integrity sha512-UWhDaJRqdPUtdK1s0sKYdoRuqK0NepjZto2UZltvuCgMoMZmdjhgz5hcRokie/3aYEaSz3xvusyoayVaq4PjRg== + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.7.4.tgz#2974fd05f4e85c695acaf497f432342de9fc0636" + integrity sha512-X8e3tcPEKnwwPVG+vP/vSqEShkwODOEeyQGod82qrIuidwIrfnsGn11qPM1jBLF4MqguTXXYzm58d0dY+/wdpg== dependencies: - "@babel/helper-create-class-features-plugin" "^7.7.0" + "@babel/helper-create-class-features-plugin" "^7.7.4" "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-typescript" "^7.2.0" + "@babel/plugin-syntax-typescript" "^7.7.4" -"@babel/plugin-transform-unicode-regex@^7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.7.0.tgz#743d9bcc44080e3cc7d49259a066efa30f9187a3" - integrity sha512-RrThb0gdrNwFAqEAAx9OWgtx6ICK69x7i9tCnMdVrxQwSDp/Abu9DXFU5Hh16VP33Rmxh04+NGW28NsIkFvFKA== +"@babel/plugin-transform-unicode-regex@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.7.4.tgz#a3c0f65b117c4c81c5b6484f2a5e7b95346b83ae" + integrity sha512-N77UUIV+WCvE+5yHw+oks3m18/umd7y392Zv7mYTpFqHtkpcc+QUz+gLJNTWVlWROIWeLqY0f3OjZxV5TcXnRw== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.7.0" + "@babel/helper-create-regexp-features-plugin" "^7.7.4" "@babel/helper-plugin-utils" "^7.0.0" "@babel/preset-env@^7.0.0": - version "7.7.1" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.7.1.tgz#04a2ff53552c5885cf1083e291c8dd5490f744bb" - integrity sha512-/93SWhi3PxcVTDpSqC+Dp4YxUu3qZ4m7I76k0w73wYfn7bGVuRIO4QUz95aJksbS+AD1/mT1Ie7rbkT0wSplaA== + version "7.7.7" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.7.7.tgz#c294167b91e53e7e36d820e943ece8d0c7fe46ac" + integrity sha512-pCu0hrSSDVI7kCVUOdcMNQEbOPJ52E+LrQ14sN8uL2ALfSqePZQlKrOy+tM4uhEdYlCHi4imr8Zz2cZe9oSdIg== dependencies: - "@babel/helper-module-imports" "^7.7.0" + "@babel/helper-module-imports" "^7.7.4" "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-proposal-async-generator-functions" "^7.7.0" - "@babel/plugin-proposal-dynamic-import" "^7.7.0" - "@babel/plugin-proposal-json-strings" "^7.2.0" - "@babel/plugin-proposal-object-rest-spread" "^7.6.2" - "@babel/plugin-proposal-optional-catch-binding" "^7.2.0" - "@babel/plugin-proposal-unicode-property-regex" "^7.7.0" - "@babel/plugin-syntax-async-generators" "^7.2.0" - "@babel/plugin-syntax-dynamic-import" "^7.2.0" - "@babel/plugin-syntax-json-strings" "^7.2.0" - "@babel/plugin-syntax-object-rest-spread" "^7.2.0" - "@babel/plugin-syntax-optional-catch-binding" "^7.2.0" - "@babel/plugin-syntax-top-level-await" "^7.7.0" - "@babel/plugin-transform-arrow-functions" "^7.2.0" - "@babel/plugin-transform-async-to-generator" "^7.7.0" - "@babel/plugin-transform-block-scoped-functions" "^7.2.0" - "@babel/plugin-transform-block-scoping" "^7.6.3" - "@babel/plugin-transform-classes" "^7.7.0" - "@babel/plugin-transform-computed-properties" "^7.2.0" - "@babel/plugin-transform-destructuring" "^7.6.0" - "@babel/plugin-transform-dotall-regex" "^7.7.0" - "@babel/plugin-transform-duplicate-keys" "^7.5.0" - "@babel/plugin-transform-exponentiation-operator" "^7.2.0" - "@babel/plugin-transform-for-of" "^7.4.4" - "@babel/plugin-transform-function-name" "^7.7.0" - "@babel/plugin-transform-literals" "^7.2.0" - "@babel/plugin-transform-member-expression-literals" "^7.2.0" - "@babel/plugin-transform-modules-amd" "^7.5.0" - "@babel/plugin-transform-modules-commonjs" "^7.7.0" - "@babel/plugin-transform-modules-systemjs" "^7.7.0" - "@babel/plugin-transform-modules-umd" "^7.7.0" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.7.0" - "@babel/plugin-transform-new-target" "^7.4.4" - "@babel/plugin-transform-object-super" "^7.5.5" - "@babel/plugin-transform-parameters" "^7.4.4" - "@babel/plugin-transform-property-literals" "^7.2.0" - "@babel/plugin-transform-regenerator" "^7.7.0" - "@babel/plugin-transform-reserved-words" "^7.2.0" - "@babel/plugin-transform-shorthand-properties" "^7.2.0" - "@babel/plugin-transform-spread" "^7.6.2" - "@babel/plugin-transform-sticky-regex" "^7.2.0" - "@babel/plugin-transform-template-literals" "^7.4.4" - "@babel/plugin-transform-typeof-symbol" "^7.2.0" - "@babel/plugin-transform-unicode-regex" "^7.7.0" - "@babel/types" "^7.7.1" + "@babel/plugin-proposal-async-generator-functions" "^7.7.4" + "@babel/plugin-proposal-dynamic-import" "^7.7.4" + "@babel/plugin-proposal-json-strings" "^7.7.4" + "@babel/plugin-proposal-object-rest-spread" "^7.7.7" + "@babel/plugin-proposal-optional-catch-binding" "^7.7.4" + "@babel/plugin-proposal-unicode-property-regex" "^7.7.7" + "@babel/plugin-syntax-async-generators" "^7.7.4" + "@babel/plugin-syntax-dynamic-import" "^7.7.4" + "@babel/plugin-syntax-json-strings" "^7.7.4" + "@babel/plugin-syntax-object-rest-spread" "^7.7.4" + "@babel/plugin-syntax-optional-catch-binding" "^7.7.4" + "@babel/plugin-syntax-top-level-await" "^7.7.4" + "@babel/plugin-transform-arrow-functions" "^7.7.4" + "@babel/plugin-transform-async-to-generator" "^7.7.4" + "@babel/plugin-transform-block-scoped-functions" "^7.7.4" + "@babel/plugin-transform-block-scoping" "^7.7.4" + "@babel/plugin-transform-classes" "^7.7.4" + "@babel/plugin-transform-computed-properties" "^7.7.4" + "@babel/plugin-transform-destructuring" "^7.7.4" + "@babel/plugin-transform-dotall-regex" "^7.7.7" + "@babel/plugin-transform-duplicate-keys" "^7.7.4" + "@babel/plugin-transform-exponentiation-operator" "^7.7.4" + "@babel/plugin-transform-for-of" "^7.7.4" + "@babel/plugin-transform-function-name" "^7.7.4" + "@babel/plugin-transform-literals" "^7.7.4" + "@babel/plugin-transform-member-expression-literals" "^7.7.4" + "@babel/plugin-transform-modules-amd" "^7.7.5" + "@babel/plugin-transform-modules-commonjs" "^7.7.5" + "@babel/plugin-transform-modules-systemjs" "^7.7.4" + "@babel/plugin-transform-modules-umd" "^7.7.4" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.7.4" + "@babel/plugin-transform-new-target" "^7.7.4" + "@babel/plugin-transform-object-super" "^7.7.4" + "@babel/plugin-transform-parameters" "^7.7.7" + "@babel/plugin-transform-property-literals" "^7.7.4" + "@babel/plugin-transform-regenerator" "^7.7.5" + "@babel/plugin-transform-reserved-words" "^7.7.4" + "@babel/plugin-transform-shorthand-properties" "^7.7.4" + "@babel/plugin-transform-spread" "^7.7.4" + "@babel/plugin-transform-sticky-regex" "^7.7.4" + "@babel/plugin-transform-template-literals" "^7.7.4" + "@babel/plugin-transform-typeof-symbol" "^7.7.4" + "@babel/plugin-transform-unicode-regex" "^7.7.4" + "@babel/types" "^7.7.4" browserslist "^4.6.0" - core-js-compat "^3.1.1" + core-js-compat "^3.6.0" invariant "^2.2.2" js-levenshtein "^1.1.3" semver "^5.5.0" -"@babel/template@^7.0.0", "@babel/template@^7.2.2", "@babel/template@^7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.7.0.tgz#4fadc1b8e734d97f56de39c77de76f2562e597d0" - integrity sha512-OKcwSYOW1mhWbnTBgQY5lvg1Fxg+VyfQGjcBduZFljfc044J5iDlnDSfhQ867O17XHiSCxYHUxHg2b7ryitbUQ== +"@babel/template@^7.0.0", "@babel/template@^7.2.2", "@babel/template@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.7.4.tgz#428a7d9eecffe27deac0a98e23bf8e3675d2a77b" + integrity sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw== dependencies: "@babel/code-frame" "^7.0.0" - "@babel/parser" "^7.7.0" - "@babel/types" "^7.7.0" + "@babel/parser" "^7.7.4" + "@babel/types" "^7.7.4" -"@babel/traverse@^7.0.0", "@babel/traverse@^7.2.3", "@babel/traverse@^7.7.0", "@babel/traverse@^7.7.2": - version "7.7.2" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.7.2.tgz#ef0a65e07a2f3c550967366b3d9b62a2dcbeae09" - integrity sha512-TM01cXib2+rgIZrGJOLaHV/iZUAxf4A0dt5auY6KNZ+cm6aschuJGqKJM3ROTt3raPUdIDk9siAufIFEleRwtw== +"@babel/traverse@^7.0.0", "@babel/traverse@^7.2.3", "@babel/traverse@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.7.4.tgz#9c1e7c60fb679fe4fcfaa42500833333c2058558" + integrity sha512-P1L58hQyupn8+ezVA2z5KBm4/Zr4lCC8dwKCMYzsa5jFMDMQAzaBNy9W5VjB+KAmBjb40U7a/H6ao+Xo+9saIw== dependencies: "@babel/code-frame" "^7.5.5" - "@babel/generator" "^7.7.2" - "@babel/helper-function-name" "^7.7.0" - "@babel/helper-split-export-declaration" "^7.7.0" - "@babel/parser" "^7.7.2" - "@babel/types" "^7.7.2" + "@babel/generator" "^7.7.4" + "@babel/helper-function-name" "^7.7.4" + "@babel/helper-split-export-declaration" "^7.7.4" + "@babel/parser" "^7.7.4" + "@babel/types" "^7.7.4" debug "^4.1.0" globals "^11.1.0" lodash "^4.17.13" -"@babel/types@^7.0.0", "@babel/types@^7.3.3", "@babel/types@^7.7.0", "@babel/types@^7.7.1", "@babel/types@^7.7.2": - version "7.7.2" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.7.2.tgz#550b82e5571dcd174af576e23f0adba7ffc683f7" - integrity sha512-YTf6PXoh3+eZgRCBzzP25Bugd2ngmpQVrk7kXX0i5N9BO7TFBtIgZYs7WtxtOGs8e6A4ZI7ECkbBCEHeXocvOA== +"@babel/types@^7.0.0", "@babel/types@^7.3.3", "@babel/types@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.7.4.tgz#516570d539e44ddf308c07569c258ff94fde9193" + integrity sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA== dependencies: esutils "^2.0.2" lodash "^4.17.13" @@ -1375,24 +1375,16 @@ nullthrows "^1.1.1" physical-cpu-count "^2.0.0" -"@types/prop-types@*": - version "15.7.3" - resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7" - integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw== +"@types/color-name@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" + integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== "@types/q@^1.5.1": version "1.5.2" resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8" integrity sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw== -"@types/react@^16.8.12", "@types/react@^16.8.6": - version "16.9.11" - resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.11.tgz#70e0b7ad79058a7842f25ccf2999807076ada120" - integrity sha512-UBT4GZ3PokTXSWmdgC/GeCGEJXE5ofWyibCcecRLUVN2ZBpXQGVgQGtG2foS7CrTKFKlQVVswLvf7Js6XA/CVQ== - dependencies: - "@types/prop-types" "*" - csstype "^2.2.0" - abab@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.3.tgz#623e2075e02eb2d3f2475e49f99c91846467907a" @@ -1427,9 +1419,9 @@ acorn@^5.0.0: integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== acorn@^6.0.1, acorn@^6.0.4: - version "6.3.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.3.0.tgz#0087509119ffa4fc0a0041d1e93a417e68cb856e" - integrity sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA== + version "6.4.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.0.tgz#b659d2ffbafa24baf5db1cdbb2c94a983ecd2784" + integrity sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw== ajv@^6.5.5: version "6.10.2" @@ -1478,6 +1470,11 @@ ansi-regex@^4.1.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== +ansi-regex@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" + integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== + ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" @@ -1490,6 +1487,14 @@ ansi-styles@^3.2.0, ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359" + integrity sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA== + dependencies: + "@types/color-name" "^1.1.1" + color-convert "^2.0.1" + aproba@^1.0.3: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" @@ -1540,10 +1545,10 @@ array-unique@^0.3.2: resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= -arrify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" - integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= +arrify@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" + integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug== asn1.js@^4.0.0: version "4.10.1" @@ -1584,6 +1589,11 @@ astral-regex@^1.0.0: resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== +astral-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" + integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== + async-limiter@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" @@ -1594,17 +1604,15 @@ asynckit@^0.4.0: resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= -atob@^2.1.1: +atob@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== -auto-bind@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/auto-bind/-/auto-bind-2.1.1.tgz#8ae509671ecdfbd5009fc99b0f19ae9c3a2abf50" - integrity sha512-NUwV1i9D3vxxY1KnfZgSZ716d6ovY7o8LfOwLhGIPFBowIb6Ln6DBW64+jCqPzUznel2hRSkQnYQqvh7/ldw8A== - dependencies: - "@types/react" "^16.8.12" +auto-bind@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/auto-bind/-/auto-bind-3.0.0.tgz#67773e64899b228f6d2a841709e7e086cfed31a3" + integrity sha512-v0A231a/lfOo6kxQtmEkdBfTApvC21aJYukA8pkKnoTvVqh3Wmm7/Rwy4GBCHTTHVoLVA5qsBDDvf1XY1nIV2g== aws-sign2@~0.7.0: version "0.7.0" @@ -1612,9 +1620,9 @@ aws-sign2@~0.7.0: integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= aws4@^1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" - integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ== + version "1.9.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.0.tgz#24390e6ad61386b0a747265754d2a17219de862c" + integrity sha512-Uvq6hVe90D0B2WEnUqtdgY1bATGz3mw33nH9Y+dmA+w5DHvUmBgkr5rM/KCHpCsiFNRUfokW/szpPPgMK2hm4A== babel-plugin-dynamic-import-node@^2.3.0: version "2.3.0" @@ -1819,14 +1827,14 @@ browserify-zlib@^0.2.0: dependencies: pako "~1.0.5" -browserslist@^4.0.0, browserslist@^4.6.0, browserslist@^4.6.6, browserslist@^4.7.2: - version "4.7.3" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.7.3.tgz#02341f162b6bcc1e1028e30624815d4924442dc3" - integrity sha512-jWvmhqYpx+9EZm/FxcZSbUZyDEvDTLDi3nSAKbzEkyWvtI0mNSmUosey+5awDW1RUlrgXbQb5A6qY1xQH9U6MQ== +browserslist@^4.0.0, browserslist@^4.6.0, browserslist@^4.6.6, browserslist@^4.8.3: + version "4.8.3" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.8.3.tgz#65802fcd77177c878e015f0e3189f2c4f627ba44" + integrity sha512-iU43cMMknxG1ClEZ2MDKeonKE1CCrFVkQK2AqO2YWFmvIrx4JWrvQ4w4hQez6EpVI8rHTtqh/ruHHDHSOKxvUg== dependencies: - caniuse-lite "^1.0.30001010" - electron-to-chromium "^1.3.306" - node-releases "^1.1.40" + caniuse-lite "^1.0.30001017" + electron-to-chromium "^1.3.322" + node-releases "^1.1.44" buffer-equal@0.0.1: version "0.0.1" @@ -1906,10 +1914,10 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001010: - version "1.0.30001011" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001011.tgz#0d6c4549c78c4a800bb043a83ca0cbe0aee6c6e1" - integrity sha512-h+Eqyn/YA6o6ZTqpS86PyRmNWOs1r54EBDcd2NTwwfsXQ8re1B38SnB+p2RKF8OUsyEIjeDU8XGec1RGO/wYCg== +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001017: + version "1.0.30001019" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001019.tgz#857e3fccaad2b2feb3f1f6d8a8f62d747ea648e1" + integrity sha512-6ljkLtF1KM5fQ+5ZN0wuyVvvebJxgJPTmScOMaFuQN2QuOzvRJnWSKfzQskQU5IOU4Gap3zasYPIinzwUjoj/g== caseless@~0.12.0: version "0.12.0" @@ -1936,6 +1944,14 @@ chalk@^2.0.0, chalk@^2.1.0, chalk@^2.4.0, chalk@^2.4.1, chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" +chalk@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" + integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + chownr@^1.1.1: version "1.1.3" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.3.tgz#42d837d5239688d55f303003a508230fa6727142" @@ -1978,6 +1994,13 @@ cli-cursor@^2.1.0: dependencies: restore-cursor "^2.0.0" +cli-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" + integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== + dependencies: + restore-cursor "^3.1.0" + cli-spinners@^1.0.0: version "1.3.1" resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-1.3.1.tgz#002c1990912d0d59580c93bd36c056de99e4259a" @@ -1988,13 +2011,18 @@ cli-spinners@^2.0.0: resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.2.0.tgz#e8b988d9206c692302d8ee834e7a85c0144d8f77" integrity sha512-tgU3fKwzYjiLEQgPMD9Jt+JjHVL9kW93FiIMX/l7rivvOD4/LL0Mf7gda3+4U2KJBloybwgj5KEoQgGRioMiKQ== -cli-truncate@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-1.1.0.tgz#2b2dfd83c53cfd3572b87fc4d430a808afb04086" - integrity sha512-bAtZo0u82gCfaAGfSNxUdTI9mNyza7D8w4CVCcaOsy7sgwDzvx6ekr6cuWJqY3UGzgnQ1+4wgENup5eIhgxEYA== +cli-truncate@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-2.1.0.tgz#c39e28bf05edcde5be3b98992a22deed5a2b93c7" + integrity sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg== dependencies: - slice-ansi "^1.0.0" - string-width "^2.0.0" + slice-ansi "^3.0.0" + string-width "^4.2.0" + +clipboard-js@^0.3.6: + version "0.3.6" + resolved "https://registry.yarnpkg.com/clipboard-js/-/clipboard-js-0.3.6.tgz#6260add69b5318fde40b80f9d3c8c863efdaf339" + integrity sha512-hyrmvbrYCeRBHdiR3KrEz0tmrUTXXEU8HLeGW0Y0icUSwYmAsmc+d6wfE4EDb/TxZmAVJG0eTfMlulCIT+ecfw== cliui@^5.0.0: version "5.0.0" @@ -2030,9 +2058,9 @@ code-point-at@^1.0.0: integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= coffeescript@^2.0.3: - version "2.4.1" - resolved "https://registry.yarnpkg.com/coffeescript/-/coffeescript-2.4.1.tgz#815fd337df0a34d49e74a98a6ebea9c3e7930f70" - integrity sha512-34GV1aHrsMpTaO3KfMJL40ZNuvKDR/g98THHnE9bQj8HjMaZvSrLik99WWqyMhRtbe8V5hpx5iLgdcSvM/S2wg== + version "2.5.0" + resolved "https://registry.yarnpkg.com/coffeescript/-/coffeescript-2.5.0.tgz#9ce853766fa8363384d80f06f79fa8d5b13f566f" + integrity sha512-RgTKZhAeKVFuGtce/d3U1x1h5W75AoYFQszNlGrtSIbexC9jowaZo574uUvc9zoNQSDLMWXVtsus9usMtbFU+w== collection-visit@^1.0.0: version "1.0.0" @@ -2049,12 +2077,19 @@ color-convert@^1.9.0, color-convert@^1.9.1: dependencies: color-name "1.1.3" +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + color-name@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= -color-name@^1.0.0: +color-name@^1.0.0, color-name@~1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== @@ -2157,23 +2192,23 @@ copy-descriptor@^0.1.0: resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= -core-js-compat@^3.1.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.4.1.tgz#e12c5a3ef9fcb50fd9d9a32805bfe674f9139246" - integrity sha512-YdeJI26gLc0CQJ9asLE5obEgBz2I0+CIgnoTbS2T0d5IPQw/OCgCIFR527RmpduxjrB3gSEHoGOCTq9sigOyfw== +core-js-compat@^3.6.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.6.2.tgz#314ca8b84d5e71c27c19f1ecda966501b1cf1f10" + integrity sha512-+G28dzfYGtAM+XGvB1C5AS1ZPKfQ47HLhcdeIQdZgQnJVdp7/D0m+W/TErwhgsX6CujRUk/LebB6dCrKrtJrvQ== dependencies: - browserslist "^4.7.2" - semver "^6.3.0" + browserslist "^4.8.3" + semver "7.0.0" core-js@^2.4.0: - version "2.6.10" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.10.tgz#8a5b8391f8cc7013da703411ce5b585706300d7f" - integrity sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA== + version "2.6.11" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c" + integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg== core-js@^3.2.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.4.1.tgz#76dd6828412900ab27c8ce0b22e6114d7ce21b18" - integrity sha512-KX/dnuY/J8FtEwbnrzmAjUYgLqtk+cxM86hfG60LGiW3MmltIc2yAmDgBgEkfm0blZhUrdr1Zd84J2Y14mLxzg== + version "3.6.2" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.2.tgz#2799ea1a59050f0acf50dfe89b916d6503b16caa" + integrity sha512-hIE5dXkRzRvnZ5vhkRfQxUvDxQZmD9oueA08jDYRBKJHx+VIl/Pne/e0A4x9LObEEthC/TqiZybUoNM4tRgnKg== core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" @@ -2418,11 +2453,6 @@ cssstyle@^1.1.1: dependencies: cssom "0.3.x" -csstype@^2.2.0: - version "2.6.7" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.7.tgz#20b0024c20b6718f4eda3853a1f5a1cce7f5e4a5" - integrity sha512-9Mcn9sFbGBAdmimWb2gLVDtFJzeKtDGIr76TUqmjZrw9LFXBMSU70lcs+C0/7fyCd6iBDqmksUcCOUIkisPHsQ== - d3-hierarchy@^1.1.9: version "1.1.9" resolved "https://registry.yarnpkg.com/d3-hierarchy/-/d3-hierarchy-1.1.9.tgz#2f6bee24caaea43f8dc37545fa01628559647a83" @@ -2445,9 +2475,9 @@ data-urls@^1.1.0: whatwg-url "^7.0.0" deasync@^0.1.14: - version "0.1.16" - resolved "https://registry.yarnpkg.com/deasync/-/deasync-0.1.16.tgz#44195eb4330fc9fc487f31ec614cbbdd57633897" - integrity sha512-FNCjDwxGbhK+Ye8fmE3p2ahIjERhkbuwX+WVGZPtSbAh9LfE1Saa2p0l+f0t11sIlk9D8W+Bym+cDp6r5yghAQ== + version "0.1.19" + resolved "https://registry.yarnpkg.com/deasync/-/deasync-0.1.19.tgz#e7ea89fcc9ad483367e8a48fe78f508ca86286e8" + integrity sha512-oh3MRktfnPlLysCPpBpKZZzb4cUC/p0aA3SyRGp15lN30juJBTo/CiD0d4fR+f1kBtUQoJj1NE9RPNWQ7BQ9Mg== dependencies: bindings "^1.5.0" node-addon-api "^1.7.1" @@ -2658,15 +2688,15 @@ ejs@^2.6.1: resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.7.4.tgz#48661287573dcc53e366c7a1ae52c3a120eec9ba" integrity sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA== -electron-to-chromium@^1.3.306: - version "1.3.307" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.307.tgz#e9b98901371d20164af7c0ca5bc820bd4305ccd3" - integrity sha512-01rTsAqHwf3D2X6NtlUvzB2hxDj67kiTVIO5GWdFb2unA0QvFvrjyrtc993ByRLF+surlr+9AvJdD0UYs5HzwA== +electron-to-chromium@^1.3.322: + version "1.3.328" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.328.tgz#a619575c42f1d5b443103664f25ffa5a80190ee5" + integrity sha512-x4XefnFxDxFwaQ01d/pppJP9meWhOIJ/gtI6/4jqkpsadq79uL7NYSaX64naLmJqvzUBjSrO3IM2+1b/W9KdPg== elliptic@^6.0.0: - version "6.5.1" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.1.tgz#c380f5f909bf1b9b4428d028cd18d3b0efd6b52b" - integrity sha512-xvJINNLbTeWQjrl6X+7eQCrIy/YPv5XCpKW6kB5mKvtnGILoLDcySuwomfdzt0BMdLNVnuRNTuzKNHj0bva1Cg== + version "6.5.2" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.2.tgz#05c5678d7173c049d8ca433552224a495d0e3762" + integrity sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw== dependencies: bn.js "^4.4.0" brorand "^1.0.1" @@ -2681,6 +2711,11 @@ emoji-regex@^7.0.1: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + emojis-list@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" @@ -2724,23 +2759,24 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.12.0, es-abstract@^1.5.1: - version "1.16.0" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.16.0.tgz#d3a26dc9c3283ac9750dca569586e976d9dcc06d" - integrity sha512-xdQnfykZ9JMEiasTAJZJdMWCQ1Vm00NBw79/AWi7ELfZuuPCSOMDZbT9mkOfSctVtfhb+sAAzrm+j//GjjLHLg== +es-abstract@^1.17.0-next.1: + version "1.17.0" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.0.tgz#f42a517d0036a5591dbb2c463591dc8bb50309b1" + integrity sha512-yYkE07YF+6SIBmg1MsJ9dlub5L48Ek7X0qz+c/CPCHS9EBXfESorzng4cJQjJW5/pB6vDF41u7F8vUhLVDqIug== dependencies: - es-to-primitive "^1.2.0" + es-to-primitive "^1.2.1" function-bind "^1.1.1" has "^1.0.3" - has-symbols "^1.0.0" - is-callable "^1.1.4" - is-regex "^1.0.4" - object-inspect "^1.6.0" + has-symbols "^1.0.1" + is-callable "^1.1.5" + is-regex "^1.0.5" + object-inspect "^1.7.0" object-keys "^1.1.1" - string.prototype.trimleft "^2.1.0" - string.prototype.trimright "^2.1.0" + object.assign "^4.1.0" + string.prototype.trimleft "^2.1.1" + string.prototype.trimright "^2.1.1" -es-to-primitive@^1.2.0: +es-to-primitive@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== @@ -2760,9 +2796,9 @@ escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= escodegen@^1.11.0, escodegen@^1.11.1: - version "1.12.0" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.12.0.tgz#f763daf840af172bb3a2b6dd7219c0e17f7ff541" - integrity sha512-TuA+EhsanGcme5T3R0L80u4t8CpbXQjegRmf7+FPTJrtCTErXFeelblRgHQa1FofEzqYYJmJ/OqjTwREp9qgmg== + version "1.12.1" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.12.1.tgz#08770602a74ac34c7a90ca9229e7d51e379abc76" + integrity sha512-Q8t2YZ+0e0pc7NRVj3B4tSQ9rim1oi4Fh46k2xhJ2qOiEwhQfdjyEQddWdj7ZFaKmU+5104vn1qrcjEPWq+bgQ== dependencies: esprima "^3.1.3" estraverse "^4.2.0" @@ -2899,9 +2935,9 @@ fast-deep-equal@^2.0.1: integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= fast-glob@^3.0.4: - version "3.1.0" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.1.0.tgz#77375a7e3e6f6fc9b18f061cddd28b8d1eec75ae" - integrity sha512-TrUz3THiq2Vy3bjfQUB2wNyPdGBeGmdjbzzBLhfHN4YFurYptCKwGq/TfiRavbGywFRzY6U2CdmQ1zmsY5yYaw== + version "3.1.1" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.1.1.tgz#87ee30e9e9f3eb40d6f254a7997655da753d7c82" + integrity sha512-nTCREpBY8w8r+boyFYAx21iL6faSsQynliPHM4Uf56SbkyohCNxpVPEH9xrF5TXKy+IsjkPUHDKiUkzBVRXn9g== dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" @@ -2910,9 +2946,9 @@ fast-glob@^3.0.4: micromatch "^4.0.2" fast-json-stable-stringify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" - integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== fast-levenshtein@~2.0.6: version "2.0.6" @@ -3153,7 +3189,12 @@ has-flag@^3.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= -has-symbols@^1.0.0: +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-symbols@^1.0.0, has-symbols@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== @@ -3389,28 +3430,27 @@ ink-spinner@^3.0.1: prop-types "^15.5.10" ink@^2.1.1: - version "2.5.0" - resolved "https://registry.yarnpkg.com/ink/-/ink-2.5.0.tgz#66cf988b65ca06d14f00f385eb531fde29f95819" - integrity sha512-HUkVglJ11cXK+W1a5cKNoOCxLkDi5hbDMAWSFDcwF2kpNd0eoX+2/cpaTP9BTFaQ8RJk7O59NxKMmyPXkmxo7w== + version "2.6.0" + resolved "https://registry.yarnpkg.com/ink/-/ink-2.6.0.tgz#04acefbed32f6ef9ed20512c51ec8b8e09a890c5" + integrity sha512-nD/wlSuB6WnFsFB0nUcOJdy28YvvDer3eo+gezjvZqojGA4Rx5sQpacvN//Aai83DRgwrRTyKBl5aciOcfP3zQ== dependencies: - "@types/react" "^16.8.6" ansi-escapes "^4.2.1" - arrify "^1.0.1" - auto-bind "^2.0.0" - chalk "^2.4.1" - cli-cursor "^2.1.0" - cli-truncate "^1.1.0" + arrify "^2.0.1" + auto-bind "^3.0.0" + chalk "^3.0.0" + cli-cursor "^3.1.0" + cli-truncate "^2.0.0" is-ci "^2.0.0" lodash.throttle "^4.1.1" log-update "^3.0.0" prop-types "^15.6.2" - react-reconciler "^0.21.0" - scheduler "^0.15.0" + react-reconciler "^0.24.0" + scheduler "^0.18.0" signal-exit "^3.0.2" - slice-ansi "^1.0.0" - string-length "^2.0.0" - widest-line "^2.0.0" - wrap-ansi "^5.0.0" + slice-ansi "^3.0.0" + string-length "^3.1.0" + widest-line "^3.1.0" + wrap-ansi "^6.2.0" yoga-layout-prebuilt "^1.9.3" invariant@^2.2.2: @@ -3459,10 +3499,10 @@ is-buffer@^1.1.5: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== -is-callable@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" - integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== +is-callable@^1.1.4, is-callable@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab" + integrity sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q== is-ci@^2.0.0: version "2.0.0" @@ -3498,9 +3538,9 @@ is-data-descriptor@^1.0.0: kind-of "^6.0.0" is-date-object@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" - integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY= + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e" + integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g== is-descriptor@^0.1.0: version "0.1.6" @@ -3554,6 +3594,11 @@ is-fullwidth-code-point@^2.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + is-glob@^4.0.0, is-glob@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" @@ -3592,12 +3637,12 @@ is-plain-object@^2.0.3, is-plain-object@^2.0.4: dependencies: isobject "^3.0.1" -is-regex@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" - integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= +is-regex@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.5.tgz#39d589a358bf18967f726967120b8fc1aed74eae" + integrity sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ== dependencies: - has "^1.0.1" + has "^1.0.3" is-resolvable@^1.0.0: version "1.1.0" @@ -3612,11 +3657,11 @@ is-svg@^3.0.0: html-comment-regex "^1.1.0" is-symbol@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38" - integrity sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw== + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937" + integrity sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ== dependencies: - has-symbols "^1.0.0" + has-symbols "^1.0.1" is-typedarray@~1.0.0: version "1.0.0" @@ -3644,9 +3689,9 @@ isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= isbinaryfile@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-4.0.2.tgz#bfc45642da645681c610cca831022e30af426488" - integrity sha512-C3FSxJdNrEr2F4z6uFtNzECDM5hXk+46fxaa+cwBe5/XrWSmzdG8DDgyjfX6/NRdBB21q2JXuRAzPCUs+fclnQ== + version "4.0.3" + resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-4.0.3.tgz#1bcca23bf4b2a95d209ec1e9da23b4d75e50fa2d" + integrity sha512-GQ9Gjhp3AsEbo8/L/pA+MYl/c4hRm5O/+uCkF4LMx1a556Wh4/d75H13qu9LldmhU4yKnlfNKBmEcCaze3b2Gw== isexe@^2.0.0: version "2.0.0" @@ -4007,17 +4052,17 @@ miller-rabin@^4.0.0: bn.js "^4.0.0" brorand "^1.0.1" -mime-db@1.42.0: - version "1.42.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.42.0.tgz#3e252907b4c7adb906597b4b65636272cf9e7bac" - integrity sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ== +mime-db@1.43.0: + version "1.43.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.43.0.tgz#0a12e0502650e473d735535050e7c8f4eb4fae58" + integrity sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ== mime-types@^2.1.12, mime-types@~2.1.19: - version "2.1.25" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.25.tgz#39772d46621f93e2a80a856c53b86a62156a6437" - integrity sha512-5KhStqB5xpTAeGqKBAMgwaYMnQik7teQN4IAzC7npDv6kzeU6prfkR67bc87J1kWMPGkoaZSq1npmexMgkmEVg== + version "2.1.26" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.26.tgz#9c921fc09b7e149a65dfdc0da4d20997200b0a06" + integrity sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ== dependencies: - mime-db "1.42.0" + mime-db "1.43.0" mime@^2.4.4: version "2.4.4" @@ -4029,6 +4074,11 @@ mimic-fn@^1.0.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + mimic-response@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.0.0.tgz#996a51c60adf12cb8a87d7fb8ef24c2f3d5ebb46" @@ -4119,9 +4169,9 @@ nice-try@^1.0.4: integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== node-abi@^2.7.0: - version "2.12.0" - resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.12.0.tgz#40e9cfabdda1837863fa825e7dfa0b15686adf6f" - integrity sha512-VhPBXCIcvmo/5K8HPmnWJyyhvgKxnHTUMXR/XwGHV68+wrgkzST4UmQrY/XszSWA5dtnXpNp528zkcyJ/pzVcw== + version "2.13.0" + resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.13.0.tgz#e2f2ec444d0aca3ea1b3874b6de41d1665828f63" + integrity sha512-9HrZGFVTR5SOu3PZAnAY2hLO36aW1wmA+FDsVkr85BTST32TLCA1H/AEcatVRAsWLyXS3bqUDYCAjq5/QGuSTA== dependencies: semver "^5.4.1" @@ -4169,10 +4219,10 @@ node-modules-regexp@^1.0.0: resolved "https://registry.yarnpkg.com/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz#8d9dbe28964a4ac5712e9131642107c71e90ec40" integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA= -node-releases@^1.1.40: - version "1.1.40" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.40.tgz#a94facfa8e2d612302601ca1361741d529c4515a" - integrity sha512-r4LPcC5b/bS8BdtWH1fbeK88ib/wg9aqmg6/s3ngNLn2Ewkn/8J6Iw3P9RTlfIAdSdvYvQl2thCY5Y+qTAQ2iQ== +node-releases@^1.1.44: + version "1.1.44" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.44.tgz#cd66438a6eb875e3eb012b6a12e48d9f4326ffd7" + integrity sha512-NwbdvJyR7nrcGrXvKAvzc5raj/NkoJudkarh2yIpJ4t0NH4aqjUDz/486P+ynIW5eokKOfzGNRdYoLfBlomruw== dependencies: semver "^6.3.0" @@ -4250,7 +4300,7 @@ object-copy@^0.1.0: define-property "^0.2.5" kind-of "^3.0.3" -object-inspect@^1.6.0: +object-inspect@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67" integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw== @@ -4283,12 +4333,12 @@ object.assign@^4.1.0: object-keys "^1.0.11" object.getownpropertydescriptors@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" - integrity sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY= + version "2.1.0" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz#369bf1f9592d8ab89d712dced5cb81c7c5352649" + integrity sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg== dependencies: - define-properties "^1.1.2" - es-abstract "^1.5.1" + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" object.pick@^1.3.0: version "1.3.0" @@ -4298,12 +4348,12 @@ object.pick@^1.3.0: isobject "^3.0.1" object.values@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.0.tgz#bf6810ef5da3e5325790eaaa2be213ea84624da9" - integrity sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg== + version "1.1.1" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.1.tgz#68a99ecde356b7e9295a3c5e0ce31dc8c953de5e" + integrity sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA== dependencies: define-properties "^1.1.3" - es-abstract "^1.12.0" + es-abstract "^1.17.0-next.1" function-bind "^1.1.1" has "^1.0.3" @@ -4328,6 +4378,13 @@ onetime@^2.0.0: dependencies: mimic-fn "^1.0.0" +onetime@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.0.tgz#fff0f3c91617fe62bb50189636e99ac8a6df7be5" + integrity sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q== + dependencies: + mimic-fn "^2.1.0" + optionator@^0.8.1: version "0.8.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" @@ -4364,9 +4421,9 @@ osenv@^0.1.4: os-tmpdir "^1.0.0" p-limit@^2.0.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537" - integrity sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg== + version "2.2.2" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.2.tgz#61279b67721f5287aa1c13a9a7fbbc48c9291b1e" + integrity sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ== dependencies: p-try "^2.0.0" @@ -4495,9 +4552,9 @@ physical-cpu-count@^2.0.0: integrity sha1-GN4vl+S/epVRrXURlCtUlverpmA= picomatch@^2.0.5: - version "2.1.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.1.1.tgz#ecdfbea7704adb5fe6fb47f9866c4c0e15e905c5" - integrity sha512-OYMyqkKzK7blWO/+XZYP6w8hH0LDvkBvdvKukti+7kqYFCiEAk+gI3DWnryapc0Dau05ugGTy0foQ6mqn4AHYA== + version "2.2.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.1.tgz#21bac888b6ed8601f831ce7816e335bc779f0a4a" + integrity sha512-ISBaA8xQNmwELC7eOjqFKMESB2VIqt4PPDD0nsS95b/9dZXvVKOlz9keMSnoGGKcOHXfTvDD6WMaRoSc9UuhRA== pirates@^4.0.0: version "4.0.1" @@ -4857,9 +4914,9 @@ postcss@^6.0.1: supports-color "^5.4.0" postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.17, postcss@^7.0.5: - version "7.0.23" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.23.tgz#9f9759fad661b15964f3cfc3140f66f1e05eadc1" - integrity sha512-hOlMf3ouRIFXD+j2VJecwssTwbvsPGJVMzupptg+85WA+i7MwyrydmQAgY3R+m0Bc0exunhbJmijy8u8+vufuQ== + version "7.0.26" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.26.tgz#5ed615cfcab35ba9bbb82414a4fa88ea10429587" + integrity sha512-IY4oRjpXWYshuTDFxMVkJDtWIk2LhsTlu8bZnbEJA4+bYT16Lvpo8Qv6EvDumhYRgzjZl489pmsY3qVgJQ08nA== dependencies: chalk "^2.4.2" source-map "^0.6.1" @@ -4966,9 +5023,9 @@ pseudomap@^1.0.2: integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= psl@^1.1.24, psl@^1.1.28: - version "1.4.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.4.0.tgz#5dd26156cdb69fa1fdb8ab1991667d3f80ced7c2" - integrity sha512-HZzqCGPecFLyoRj5HLfuDSKYTJkAfB5thKBIkRHtGjWwY7p1dAyveIbXIq4tO0KYfDF2tHqPUgY9SDnGm00uFw== + version "1.7.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.7.0.tgz#f1c4c47a8ef97167dea5d6bbf4816d736e884a3c" + integrity sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ== public-encrypt@^4.0.0: version "4.0.3" @@ -5006,9 +5063,9 @@ punycode@^2.1.0, punycode@^2.1.1: integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== purgecss@^1.4.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/purgecss/-/purgecss-1.4.1.tgz#d362e63eb1ed9dd1fa1554b9fd7accb8d54e56dc" - integrity sha512-5jONV/D/3nfa+lC425+LA+OWe5/LDn4a79cac+TnzJq3VczwnWlpIDdW275hHsGhkzIlqATQsYFLW7or0cSwNQ== + version "1.4.2" + resolved "https://registry.yarnpkg.com/purgecss/-/purgecss-1.4.2.tgz#67ab50cb4f5c163fcefde56002467c974e577f41" + integrity sha512-hkOreFTgiyMHMmC2BxzdIw5DuC6kxAbP/gGOGd3MEsF3+5m69rIvUEPaxrnoUtfODTFKe9hcXjGwC6jcjoyhOw== dependencies: glob "^7.1.3" postcss "^7.0.14" @@ -5084,15 +5141,15 @@ react-is@^16.8.1: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.12.0.tgz#2cc0fe0fba742d97fd527c42a13bec4eeb06241c" integrity sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q== -react-reconciler@^0.21.0: - version "0.21.0" - resolved "https://registry.yarnpkg.com/react-reconciler/-/react-reconciler-0.21.0.tgz#8180342ab3c8295f860025a86d0a03742a294ea7" - integrity sha512-h4Rl3L3O6G9V4Ff+F+tCXX8ElDVn0Psk/odT+NPWeA55Yk5G7+kHT8D+Q3yE+51C72LbrYcX6OfLmCZ/7Nx9cw== +react-reconciler@^0.24.0: + version "0.24.0" + resolved "https://registry.yarnpkg.com/react-reconciler/-/react-reconciler-0.24.0.tgz#5a396b2c2f5efe8554134a5935f49f546723f2dd" + integrity sha512-gAGnwWkf+NOTig9oOowqid9O0HjTDC+XVGBCAmJYYJ2A2cN/O4gDdIuuUQjv8A4v6GDwVfJkagpBBLW5OW9HSw== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" prop-types "^15.6.2" - scheduler "^0.15.0" + scheduler "^0.18.0" react-refresh@^0.6.0: version "0.6.0" @@ -5114,9 +5171,9 @@ react@^16.12.0, react@^16.7.0: prop-types "^15.6.2" readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.3, readable-stream@~2.3.6: - version "2.3.6" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" - integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== dependencies: core-util-is "~1.0.0" inherits "~2.0.3" @@ -5206,9 +5263,9 @@ regjsparser@^0.1.4: jsesc "~0.5.0" regjsparser@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.0.tgz#f1e6ae8b7da2bae96c99399b868cd6c933a2ba9c" - integrity sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ== + version "0.6.2" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.2.tgz#fd62c753991467d9d1ffe0a9f67f27a529024b96" + integrity sha512-E9ghzUtoLwDekPT0DYCp+c4h+bvuUpe6rRHCTYn6eGoqj1LgKXxT6I0Il4WbjhQkOghzi/V+y03bPKvbllL93Q== dependencies: jsesc "~0.5.0" @@ -5290,9 +5347,9 @@ resolve-url@^0.2.1: integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= resolve@^1.1.5, resolve@^1.12.0, resolve@^1.3.2: - version "1.12.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.12.0.tgz#3fc644a35c84a48554609ff26ec52b66fa577df6" - integrity sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w== + version "1.14.2" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.14.2.tgz#dbf31d0fa98b1f29aa5169783b9c290cb865fea2" + integrity sha512-EjlOBLBO1kxsUxsKjLt7TAECyKW6fOh1VRkykQkKGzcBbjjPIxBqGh0jf7GJ3k/f5mxMqW3htMD3WdTUVtW8HQ== dependencies: path-parse "^1.0.6" @@ -5304,6 +5361,14 @@ restore-cursor@^2.0.0: onetime "^2.0.0" signal-exit "^3.0.2" +restore-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" + integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== + dependencies: + onetime "^5.1.0" + signal-exit "^3.0.2" + ret@~0.1.10: version "0.1.15" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" @@ -5367,9 +5432,9 @@ safe-regex@^1.1.0: integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== safer-eval@^1.3.0: - version "1.3.5" - resolved "https://registry.yarnpkg.com/safer-eval/-/safer-eval-1.3.5.tgz#a75a1193a4e1dfadd34a8c87ad08e7b978c494b1" - integrity sha512-BJ//K2Y+EgCbOHEsDGS5YahYBcYy7JcFpKDo2ba5t4MnOGHYtk7HvQkcxTDFvjQvJ0CRcdas/PyF+gTTCay+3w== + version "1.3.6" + resolved "https://registry.yarnpkg.com/safer-eval/-/safer-eval-1.3.6.tgz#ee51e3348c39fdc4117a47dfb4b69df56a2e40cf" + integrity sha512-DN9tBsZgtUOHODzSfO1nGCLhZtxc7Qq/d8/2SNxQZ9muYXZspSh1fO7HOsrf4lcelBNviAJLCxB/ggmG+jV1aw== dependencies: clones "^1.2.0" @@ -5385,14 +5450,6 @@ saxes@^3.1.9: dependencies: xmlchars "^2.1.1" -scheduler@^0.15.0: - version "0.15.0" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.15.0.tgz#6bfcf80ff850b280fed4aeecc6513bc0b4f17f8e" - integrity sha512-xAefmSfN6jqAa7Kuq7LIJY0bwAPG3xlCj0HMEBQk1lxYiDKZscY2xJ5U/61ZTrYbmNQbXa+gc7czPkVo11tnCg== - dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" - scheduler@^0.18.0: version "0.18.0" resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.18.0.tgz#5901ad6659bc1d8f3fdaf36eb7a67b0d6746b1c4" @@ -5401,6 +5458,11 @@ scheduler@^0.18.0: loose-envify "^1.1.0" object-assign "^4.1.1" +semver@7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" + integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== + semver@^5.4.1, semver@^5.5.0, semver@^5.6.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" @@ -5495,12 +5557,14 @@ simple-swizzle@^0.2.2: dependencies: is-arrayish "^0.3.1" -slice-ansi@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d" - integrity sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg== +slice-ansi@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-3.0.0.tgz#31ddc10930a1b7e0b67b08c96c2f49b77a789787" + integrity sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ== dependencies: - is-fullwidth-code-point "^2.0.0" + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" snapdragon-node@^2.0.1: version "2.1.1" @@ -5533,11 +5597,11 @@ snapdragon@^0.8.1: use "^3.1.0" source-map-resolve@^0.5.0: - version "0.5.2" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" - integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA== + version "0.5.3" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" + integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== dependencies: - atob "^2.1.1" + atob "^2.1.2" decode-uri-component "^0.2.0" resolve-url "^0.2.1" source-map-url "^0.4.0" @@ -5679,13 +5743,13 @@ string-hash@^1.1.1: resolved "https://registry.yarnpkg.com/string-hash/-/string-hash-1.1.3.tgz#e8aafc0ac1855b4666929ed7dd1275df5d6c811b" integrity sha1-6Kr8CsGFW0Zmkp7X3RJ1311sgRs= -string-length@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/string-length/-/string-length-2.0.0.tgz#d40dbb686a3ace960c1cffca562bf2c45f8363ed" - integrity sha1-1A27aGo6zpYMHP/KVivyxF+DY+0= +string-length@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/string-length/-/string-length-3.1.0.tgz#107ef8c23456e187a8abd4a61162ff4ac6e25837" + integrity sha512-Ttp5YvkGm5v9Ijagtaz1BnN+k9ObpvS0eIBblPMp2YWL8FBmi9qblQ9fexc2k/CXFgrTIteU3jAw3payCnwSTA== dependencies: astral-regex "^1.0.0" - strip-ansi "^4.0.0" + strip-ansi "^5.2.0" string-width@^1.0.1: version "1.0.2" @@ -5696,7 +5760,7 @@ string-width@^1.0.1: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.1: +"string-width@^1.0.2 || 2": version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== @@ -5713,18 +5777,27 @@ string-width@^3.0.0, string-width@^3.1.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" -string.prototype.trimleft@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz#6cc47f0d7eb8d62b0f3701611715a3954591d634" - integrity sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw== +string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" + integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.0" + +string.prototype.trimleft@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz#9bdb8ac6abd6d602b17a4ed321870d2f8dcefc74" + integrity sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag== dependencies: define-properties "^1.1.3" function-bind "^1.1.1" -string.prototype.trimright@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz#669d164be9df9b6f7559fa8e89945b168a5a6c58" - integrity sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg== +string.prototype.trimright@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz#440314b15996c866ce8a0341894d45186200c5d9" + integrity sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g== dependencies: define-properties "^1.1.3" function-bind "^1.1.1" @@ -5764,6 +5837,13 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" +strip-ansi@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" + integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== + dependencies: + ansi-regex "^5.0.0" + strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" @@ -5804,6 +5884,13 @@ supports-color@^6.1.0: dependencies: has-flag "^3.0.0" +supports-color@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1" + integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g== + dependencies: + has-flag "^4.0.0" + svgo@^1.0.0, svgo@^1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.2.tgz#b6dc511c063346c9e415b81e43401145b96d4167" @@ -5859,9 +5946,9 @@ terser@^3.7.3: source-map-support "~0.5.10" terser@^4.0.0, terser@^4.3.9: - version "4.4.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-4.4.0.tgz#22c46b4817cf4c9565434bfe6ad47336af259ac3" - integrity sha512-oDG16n2WKm27JO8h4y/w3iqBGAOSCtq7k8dRmrn4Wf9NouL0b2WpMHGChFGZq4nFAQy1FsNJrVQHfurXOSTmOA== + version "4.6.1" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.6.1.tgz#913e35e0d38a75285a7913ba01d753c4089ebdbd" + integrity sha512-w0f2OWFD7ka3zwetgVAhNMeyzEbj39ht2Tb0qKflw9PmW9Qbo5tjTh01QJLkhO9t9RDDQYvk+WXqpECI2C6i2A== dependencies: commander "^2.20.0" source-map "~0.6.1" @@ -6242,12 +6329,12 @@ wide-align@^1.1.0: dependencies: string-width "^1.0.2 || 2" -widest-line@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-2.0.1.tgz#7438764730ec7ef4381ce4df82fb98a53142a3fc" - integrity sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA== +widest-line@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca" + integrity sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg== dependencies: - string-width "^2.1.1" + string-width "^4.0.0" word-wrap@~1.2.3: version "1.2.3" @@ -6263,6 +6350,15 @@ wrap-ansi@^5.0.0, wrap-ansi@^5.1.0: string-width "^3.0.0" strip-ansi "^5.0.0" +wrap-ansi@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" From 252e486c719c54d37d7cda355d0f9a166d380fd0 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Tue, 7 Jan 2020 11:46:13 -0800 Subject: [PATCH 004/116] Added context menu --- src/App.js | 102 ++++++++++++++++++++++++++- src/Canvas.js | 30 -------- src/EventTooltip.css | 1 + src/constants.js | 15 +++- src/context/ContextMenu.css | 10 +++ src/context/ContextMenu.js | 120 ++++++++++++++++++++++++++++++++ src/context/ContextMenuItem.css | 20 ++++++ src/context/ContextMenuItem.js | 31 +++++++++ src/context/Contexts.js | 70 +++++++++++++++++++ src/context/index.js | 8 +++ src/context/useContextMenu.js | 40 +++++++++++ src/usePanAndZoom.js | 26 ++++++- 12 files changed, 440 insertions(+), 33 deletions(-) delete mode 100644 src/Canvas.js create mode 100644 src/context/ContextMenu.css create mode 100644 src/context/ContextMenu.js create mode 100644 src/context/ContextMenuItem.css create mode 100644 src/context/ContextMenuItem.js create mode 100644 src/context/Contexts.js create mode 100644 src/context/index.js create mode 100644 src/context/useContextMenu.js diff --git a/src/App.js b/src/App.js index 5640d53861867..2db7a2111ecbb 100644 --- a/src/App.js +++ b/src/App.js @@ -1,5 +1,6 @@ // @flow +import { copy } from 'clipboard-js'; import React, { Fragment, useEffect, @@ -11,6 +12,8 @@ import { unstable_batchedUpdates } from 'react-dom'; import memoize from 'memoize-one'; import usePanAndZoom from './usePanAndZoom'; import { getCanvasContext } from './canvasUtils'; +import prettyMilliseconds from 'pretty-ms'; +import { getBatchRange } from './utils'; import { durationToWidth, positionToTimestamp, @@ -39,9 +42,17 @@ import { MARKER_HEIGHT, MARKER_TICK_HEIGHT, } from './constants'; +import { + ContextMenu, + ContextMenuItem, + RegistryContext, + useContextMenu, +} from './context'; import JSON_PATH from 'url:../static/small-devtools.json'; +const CONTEXT_MENU_ID = 'canvas'; + import type { FlamechartData, ReactEvent, @@ -720,6 +731,28 @@ function App() { ); } +const copySummary = (data, measure) => { + const { batchUID, duration, priority, timestamp, type } = measure; + + const [startTime, stopTime] = getBatchRange(batchUID, priority, data); + + copy( + JSON.stringify({ + type, + timestamp: prettyMilliseconds(timestamp), + duration: prettyMilliseconds(duration), + batchDuration: prettyMilliseconds(stopTime - startTime), + }) + ); +}; + +const zoomToBatch = (data, measure, state) => { + const { batchUID, priority } = measure; + const [startTime, stopTime] = getBatchRange(batchUID, priority, data); + + state.zoomTo(startTime, stopTime); +}; + function AutoSizedCanvas({ data, flamechart, height, width }) { const canvasRef = useRef(); @@ -738,6 +771,19 @@ function AutoSizedCanvas({ data, flamechart, height, width }) { }); const hoveredEvent = getHoveredEvent(data, flamechart, state); + const [isContextMenuShown, setIsContextMenuShown] = useState(false); + + useContextMenu({ + data: { + data, + flamechart, + hoveredEvent, + state, + }, + id: CONTEXT_MENU_ID, + onChange: setIsContextMenuShown, + ref: canvasRef, + }); useLayoutEffect(() => { renderCanvas( @@ -759,7 +805,61 @@ function AutoSizedCanvas({ data, flamechart, height, width }) { height={height} width={width} /> - + + {({ data, hoveredEvent }) => { + if (hoveredEvent == null) { + return null; + } + const { event, flamechartNode, measure } = hoveredEvent; + return ( + + {event !== null && ( + copy(event.componentName)} + title="Copy component name" + > + Copy component name + + )} + {event !== null && ( + copy(event.componentStack)} + title="Copy component stack" + > + Copy component stack + + )} + {measure !== null && ( + zoomToBatch(data, measure, state)} + title="Zoom to batch" + > + Zoom to batch + + )} + {measure !== null && ( + copySummary(data, measure)} + title="Copy summary" + > + Copy summary + + )} + {flamechartNode !== null && ( + copy(flamechartNode.node.frame.file)} + title="Copy file path" + > + Copy file path + + )} + + ); + }} + + {!isContextMenuShown && ( + + )} ); } diff --git a/src/Canvas.js b/src/Canvas.js deleted file mode 100644 index f8ecb0f6d999f..0000000000000 --- a/src/Canvas.js +++ /dev/null @@ -1,30 +0,0 @@ -import React, { Fragment, useLayoutEffect, useRef } from 'react'; -import usePanAndZoom from './usePanAndZoom'; - -export default function Canvas({ - height, - renderCanvas, - renderTooltip, - scrollWidth, - width, -}) { - const canvasRef = useRef(); - - const state = usePanAndZoom(canvasRef, scrollWidth); - - useLayoutEffect(() => renderCanvas(canvasRef.current, state)); - - return ( - - - {renderTooltip(state)} -
{`canvas width: ${canvasRef.current ? canvasRef.current.width : '-'}
-canvas scrollWidth: ${canvasRef.current ? scrollWidth : '-'}
-centerX: ${state.centerX}
-zoomLevel: ${state.zoomLevel}
-canvasMouseX: ${state.canvasMouseX}
-canvasMouseY: ${state.canvasMouseY}
-caltulated ts: ${ts}`}
-
- ); -} diff --git a/src/EventTooltip.css b/src/EventTooltip.css index a0939364d29c3..4cb2acc4aa2a5 100644 --- a/src/EventTooltip.css +++ b/src/EventTooltip.css @@ -23,6 +23,7 @@ padding-top: 5px; grid-gap: 2px 5px; grid-template-columns: min-content auto; + word-break: break-word; } .DetailsGridLabel { diff --git a/src/constants.js b/src/constants.js index b51930b3405ed..4cdb676488c27 100644 --- a/src/constants.js +++ b/src/constants.js @@ -12,7 +12,20 @@ export const EVENT_SIZE = 6; export const MIN_BAR_WIDTH = 1; export const SECTION_GUTTER_SIZE = 4; -export const INTERVAL_TIMES = [10, 20, 50, 100, 200, 500, 1000, 2000, 5000]; +export const INTERVAL_TIMES = [ + 1, + 2, + 5, + 10, + 20, + 50, + 100, + 200, + 500, + 1000, + 2000, + 5000, +]; export const MIN_INTERVAL_SIZE_PX = 70; export const MAX_INTERVAL_SIZE_PX = 140; diff --git a/src/context/ContextMenu.css b/src/context/ContextMenu.css new file mode 100644 index 0000000000000..60848641f4949 --- /dev/null +++ b/src/context/ContextMenu.css @@ -0,0 +1,10 @@ +.ContextMenu { + position: absolute; + border-radius: 0.125rem; + background-color: #ffffff; + border: 1px solid #ccc; + box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.2); + font-size: 11px; + overflow: hidden; + z-index: 10000002; +} diff --git a/src/context/ContextMenu.js b/src/context/ContextMenu.js new file mode 100644 index 0000000000000..aa176f62f6a32 --- /dev/null +++ b/src/context/ContextMenu.js @@ -0,0 +1,120 @@ +// @flow + +import React, { + useContext, + useEffect, + useLayoutEffect, + useRef, + useState, +} from 'react'; +import { createPortal } from 'react-dom'; +import { RegistryContext } from './Contexts'; + +import styles from './ContextMenu.css'; + +function respositionToFit(element: HTMLElement, pageX: number, pageY: number) { + const ownerWindow = element.ownerDocument.defaultView; + if (element !== null) { + if (pageY + element.offsetHeight >= ownerWindow.innerHeight) { + if (pageY - element.offsetHeight > 0) { + element.style.top = `${pageY - element.offsetHeight}px`; + } else { + element.style.top = '0px'; + } + } else { + element.style.top = `${pageY}px`; + } + + if (pageX + element.offsetWidth >= ownerWindow.innerWidth) { + if (pageX - element.offsetWidth > 0) { + element.style.left = `${pageX - element.offsetWidth}px`; + } else { + element.style.left = '0px'; + } + } else { + element.style.left = `${pageX}px`; + } + } +} + +const HIDDEN_STATE = { + data: null, + isVisible: false, + pageX: 0, + pageY: 0, +}; + +type Props = {| + children: (data: Object) => React$Node, + id: string, +|}; + +export default function ContextMenu({ children, id }: Props) { + const { hideMenu, registerMenu } = useContext(RegistryContext); + + const [state, setState] = useState(HIDDEN_STATE); + + const bodyAccessorRef = useRef(null); + const containerRef = useRef(null); + const menuRef = useRef(null); + + useEffect(() => { + const ownerDocument = bodyAccessorRef.current.ownerDocument; + containerRef.current = ownerDocument.createElement('div'); + ownerDocument.body.appendChild(containerRef.current); + return () => { + ownerDocument.body.removeChild(containerRef.current); + }; + }, []); + + useEffect(() => { + const showMenu = ({ data, pageX, pageY }) => { + setState({ data, isVisible: true, pageX, pageY }); + }; + const hideMenu = () => setState(HIDDEN_STATE); + return registerMenu(id, showMenu, hideMenu); + }, [id]); + + useLayoutEffect(() => { + if (!state.isVisible) { + return; + } + + const menu = menuRef.current; + + const hideUnlessContains = event => { + if (!menu.contains(event.target)) { + hideMenu(); + } + }; + + const ownerDocument = containerRef.current.ownerDocument; + ownerDocument.addEventListener('mousedown', hideUnlessContains); + ownerDocument.addEventListener('touchstart', hideUnlessContains); + ownerDocument.addEventListener('keydown', hideUnlessContains); + + const ownerWindow = ownerDocument.defaultView; + ownerWindow.addEventListener('resize', hideMenu); + + respositionToFit(menu, state.pageX, state.pageY); + + return () => { + ownerDocument.removeEventListener('mousedown', hideUnlessContains); + ownerDocument.removeEventListener('touchstart', hideUnlessContains); + ownerDocument.removeEventListener('keydown', hideUnlessContains); + + ownerWindow.removeEventListener('resize', hideMenu); + }; + }, [state]); + + if (!state.isVisible) { + return
; + } else { + return createPortal( +
+ {children(state.data)} +
, + containerRef.current + ); + } +} diff --git a/src/context/ContextMenuItem.css b/src/context/ContextMenuItem.css new file mode 100644 index 0000000000000..19fd8284a47cb --- /dev/null +++ b/src/context/ContextMenuItem.css @@ -0,0 +1,20 @@ +.ContextMenuItem { + display: flex; + align-items: center; + color: #333; + padding: 0.5rem 0.75rem; + cursor: default; + border-top: 1px solid #ccc; +} +.ContextMenuItem:first-of-type { + border-top: none; +} +.ContextMenuItem:hover, +.ContextMenuItem:focus { + outline: 0; + background-color: rgba(0, 136, 250, 0.1); +} +.ContextMenuItem:active { + background-color: #0088fa; + color: #fff; +} diff --git a/src/context/ContextMenuItem.js b/src/context/ContextMenuItem.js new file mode 100644 index 0000000000000..90d3b4b79fb27 --- /dev/null +++ b/src/context/ContextMenuItem.js @@ -0,0 +1,31 @@ +// @flow + +import React, { useContext } from 'react'; +import { RegistryContext } from './Contexts'; + +import styles from './ContextMenuItem.css'; + +type Props = {| + children: React$Node, + onClick: () => void, + title: string, +|}; + +export default function ContextMenuItem({ children, onClick, title }: Props) { + const { hideMenu } = useContext(RegistryContext); + + const handleClick = event => { + onClick(); + hideMenu(); + }; + + return ( +
+ {children} +
+ ); +} diff --git a/src/context/Contexts.js b/src/context/Contexts.js new file mode 100644 index 0000000000000..c0803051ab7db --- /dev/null +++ b/src/context/Contexts.js @@ -0,0 +1,70 @@ +// @flow + +import { createContext } from 'react'; + +export type ShowFn = ({| data: Object, pageX: number, pageY: number |}) => void; +export type HideFn = () => void; + +const idToShowFnMap = new Map(); +const idToHideFnMap = new Map(); + +let currentHideFn = null; +let currentOnChange = null; + +function hideMenu() { + if (typeof currentHideFn === 'function') { + currentHideFn(); + + if (typeof currentOnChange === 'function') { + currentOnChange(false); + } + } + + currentHideFn = null; + currentOnChange = null; +} + +function showMenu({ + data, + id, + onChange, + pageX, + pageY, +}: {| + data: Object, + id: string, + onChange?: Function, + pageX: number, + pageY: number, +|}) { + const showFn = idToShowFnMap.get(id); + if (typeof showFn === 'function') { + currentHideFn = idToHideFnMap.get(id); + showFn({ data, pageX, pageY }); + + if (typeof onChange === 'function') { + currentOnChange = onChange; + onChange(true); + } + } +} + +function registerMenu(id: string, showFn: ShowFn, hideFn: HideFn) { + if (idToShowFnMap.has(id)) { + throw Error(`Context menu with id "${id}" already registered.`); + } + + idToShowFnMap.set(id, showFn); + idToHideFnMap.set(id, hideFn); + + return function unregisterMenu() { + idToShowFnMap.delete(id); + idToHideFnMap.delete(id); + }; +} + +export const RegistryContext = createContext({ + hideMenu, + showMenu, + registerMenu, +}); diff --git a/src/context/index.js b/src/context/index.js new file mode 100644 index 0000000000000..6693b126ca75d --- /dev/null +++ b/src/context/index.js @@ -0,0 +1,8 @@ +// @flow + +import { RegistryContext } from './Contexts'; +import ContextMenu from './ContextMenu'; +import ContextMenuItem from './ContextMenuItem'; +import useContextMenu from './useContextMenu'; + +export { RegistryContext, ContextMenu, ContextMenuItem, useContextMenu }; diff --git a/src/context/useContextMenu.js b/src/context/useContextMenu.js new file mode 100644 index 0000000000000..6acb9e86b3eae --- /dev/null +++ b/src/context/useContextMenu.js @@ -0,0 +1,40 @@ +// @flow + +import { useContext, useEffect } from 'react'; +import { RegistryContext } from './Contexts'; + +import type { ElementRef } from 'react'; + +export default function useContextMenu({ + data, + id, + onChange, + ref, +}: {| + data: Object, + id: string, + ref: ElementRef, +|}) { + const { showMenu } = useContext(RegistryContext); + + useEffect(() => { + if (ref.current !== null) { + const handleContextMenu = event => { + event.preventDefault(); + event.stopPropagation(); + + const pageX = event.pageX || (event.touches && event.touches[0].pageX); + const pageY = event.pageY || (event.touches && event.touches[0].pageY); + + showMenu({ data, id, onChange, pageX, pageY }); + }; + + const trigger = ref.current; + trigger.addEventListener('contextmenu', handleContextMenu); + + return () => { + trigger.removeEventListener('contextmenu', handleContextMenu); + }; + } + }, [data, id, showMenu]); +} diff --git a/src/usePanAndZoom.js b/src/usePanAndZoom.js index f64f7015532a6..76301f4c595fd 100644 --- a/src/usePanAndZoom.js +++ b/src/usePanAndZoom.js @@ -23,6 +23,7 @@ const initialState = { unscaledContentHeight: 0, unscaledContentWidth: 0, zoomLevel: 1, + zoomTo: null, }; // TODO Account for fixed label width @@ -179,6 +180,19 @@ function reducer(state, action) { } } break; + case 'zoom-to': + const { startTime, stopTime } = payload; + const { canvasWidth, fixedColumnWidth } = state; + + const availableWidth = canvasWidth - fixedColumnWidth; + const newZoomLevel = availableWidth / (stopTime - startTime); + + return { + ...state, + offsetX: newZoomLevel * startTime, + zoomLevel: newZoomLevel, + }; + break; default: throw Error(`Unexpected type "${type}"`); } @@ -203,7 +217,17 @@ export default function usePanAndZoom({ unscaledContentWidth, unscaledContentHeight, }) { - const [state, dispatch] = useReducer(reducer, initialState); + const [state, dispatch] = useReducer(reducer, { + ...initialState, + zoomTo: (startTime, stopTime) => + dispatch({ + type: 'zoom-to', + payload: { + startTime, + stopTime, + }, + }), + }); // TODO This effect should run any time width or unscaledContentWidth changes useEffect(() => { From 1a662782e456bb9ffa5788434da05711fa2516c6 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Wed, 8 Jan 2020 09:11:33 -0800 Subject: [PATCH 005/116] STASHING --- src/App.js | 16 +++++++++++++++- src/EventTooltip.js | 7 ++++--- src/preprocessData.js | 2 +- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/App.js b/src/App.js index 2db7a2111ecbb..4c4b26a76d2b2 100644 --- a/src/App.js +++ b/src/App.js @@ -49,7 +49,7 @@ import { useContextMenu, } from './context'; -import JSON_PATH from 'url:../static/small-devtools.json'; +import JSON_PATH from 'url:../static/ads-manager-1.json'; const CONTEXT_MENU_ID = 'canvas'; @@ -707,6 +707,8 @@ function App() { unstable_batchedUpdates(() => { const processedData = preprocessData(data); setData(processedData); + console.log(data); + console.log(processedData); const flamechart = preprocessFlamechart(data); setFlamechart(flamechart); @@ -853,6 +855,18 @@ function AutoSizedCanvas({ data, flamechart, height, width }) { Copy file path )} + {flamechartNode !== null && ( + + copy( + `line ${flamechartNode.node.frame.line}, column ${flamechartNode.node.frame.col}` + ) + } + title="Copy location" + > + Copy location + + )} ); }} diff --git a/src/EventTooltip.js b/src/EventTooltip.js index 03b6247d2691c..fbe6b45eb8b82 100644 --- a/src/EventTooltip.js +++ b/src/EventTooltip.js @@ -106,7 +106,7 @@ function formatComponentStack(componentStack) { const TooltipFlamechartNode = ({ data, flamechartNode, tooltipRef }) => { const { end, node, start } = flamechartNode; - const { name, file } = node.frame; + const { col, file, line, name } = node.frame; return (
{ > {prettyMilliseconds((end - start) / 1000)} {name}
-
Script URL:
- {file} +
Script URL:
{file} +
Location:
+ line {line}, column {col}
); diff --git a/src/preprocessData.js b/src/preprocessData.js index 1f9bfb23b682c..093f8e1ebff44 100644 --- a/src/preprocessData.js +++ b/src/preprocessData.js @@ -226,7 +226,7 @@ export default function reactProfilerProcessor( name === '--layout-effects-start' ? 'layout-effects' : 'passive-effects'; - throwIfIncomplete(type); + //throwIfIncomplete(type); markWorkStarted(type, startTime); } else if ( name === '--layout-effects-stop' || From 9887a573af1efff6b2cd7b81ad653417e93c8419 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Fri, 5 Jun 2020 09:24:04 -0700 Subject: [PATCH 006/116] Work in progress lanes --- src/App.js | 261 +++++++++++++++++++++++++----------------- src/constants.js | 4 +- src/preprocessData.js | 18 ++- src/types.js | 1 + 4 files changed, 171 insertions(+), 113 deletions(-) diff --git a/src/App.js b/src/App.js index 4c4b26a76d2b2..00b0ff3091755 100644 --- a/src/App.js +++ b/src/App.js @@ -49,7 +49,8 @@ import { useContextMenu, } from './context'; -import JSON_PATH from 'url:../static/ads-manager-1.json'; +import JSON_PATH from 'url:../static/small-devtools.json'; +//import JSON_PATH from 'url:../static/initial-render.json'; const CONTEXT_MENU_ID = 'canvas'; @@ -68,21 +69,11 @@ const TEXT_CSS_PIXELS_OFFSET_TOP = 11; const FONT_SIZE = 10; const BORDER_OPACITY = 0.4; -const REACT_DEVTOOLS_FONT_SIZE = 12; const REACT_GUTTER_SIZE = 4; const REACT_EVENT_SIZE = 6; const REACT_WORK_SIZE = 12; -const REACT_WORK_DEPTH_OFFSET = 3; const REACT_EVENT_BORDER_SIZE = 1; const REACT_PRIORITY_BORDER_SIZE = 1; -const REACT_DEVTOOLS_PRIORITY_SIZE = - REACT_GUTTER_SIZE * 3 + - REACT_EVENT_SIZE + - REACT_WORK_SIZE + - REACT_PRIORITY_BORDER_SIZE; -const REACT_DEVTOOLS_CANVAS_HEIGHT = - (REACT_DEVTOOLS_PRIORITY_SIZE + REACT_PRIORITY_BORDER_SIZE) * - REACT_PRIORITIES.length; const FLAMECHART_FONT_SIZE = 10; const FLAMECHART_FRAME_HEIGHT = 16; @@ -107,28 +98,38 @@ function getTimeTickInterval(zoomLevel) { return interval; } -function getHoveredEvent(data, flamechart, state) { +function getHoveredEvent(schedulerCanvasHeight, data, flamechart, state) { const { canvasMouseX, canvasMouseY, offsetY } = state; if (canvasMouseX < LABEL_FIXED_WIDTH || canvasMouseY < HEADER_HEIGHT_FIXED) { return null; } - if (canvasMouseY + offsetY < REACT_DEVTOOLS_CANVAS_HEIGHT) { + if (canvasMouseY + offsetY < schedulerCanvasHeight) { if (data != null) { - const priorityIndex = Math.floor( - (canvasMouseY - HEADER_HEIGHT_FIXED + offsetY) / - REACT_DEVTOOLS_PRIORITY_SIZE - ); - if (priorityIndex >= REACT_PRIORITIES.length) { + let adjustedCanvasMouseY = canvasMouseY - HEADER_HEIGHT_FIXED + offsetY; + let priorityMinY = HEADER_HEIGHT_FIXED; + let priorityIndex = null; + let priority = null; + for (let index = 0; index < REACT_PRIORITIES.length; index++) { + priority = REACT_PRIORITIES[index]; + + const priorityHeight = getPriorityHeight(data, priority); + if ( + adjustedCanvasMouseY >= priorityMinY && + adjustedCanvasMouseY <= priorityMinY + priorityHeight + ) { + priorityIndex = index; + break; + } + priorityMinY += priorityHeight; + } + + if (priorityIndex === null) { return null; } - const priority = REACT_PRIORITIES[priorityIndex]; - const baseY = - HEADER_HEIGHT_FIXED + - REACT_DEVTOOLS_PRIORITY_SIZE * priorityIndex - - offsetY; + const baseY = priorityMinY - offsetY; const eventMinY = baseY + REACT_GUTTER_SIZE / 2; const eventMaxY = eventMinY + REACT_EVENT_SIZE + REACT_GUTTER_SIZE; const measureMinY = eventMaxY; @@ -184,10 +185,7 @@ function getHoveredEvent(data, flamechart, state) { } else { if (flamechart !== null) { const layerIndex = Math.floor( - (canvasMouseY + - offsetY - - HEADER_HEIGHT_FIXED - - REACT_DEVTOOLS_CANVAS_HEIGHT) / + (canvasMouseY + offsetY - HEADER_HEIGHT_FIXED - schedulerCanvasHeight) / FLAMECHART_FRAME_HEIGHT ); const layer = flamechart.layers[layerIndex]; @@ -247,6 +245,7 @@ const trimFlamegraphText = (context, text, width) => { }; const renderReact = ({ + baseY, canvasWidth, context, eventOrMeasure, @@ -318,35 +317,10 @@ const renderReact = ({ break; } - y = - HEADER_HEIGHT_FIXED + - (REACT_DEVTOOLS_PRIORITY_SIZE * priorityIndex + - REACT_GUTTER_SIZE + - REACT_EVENT_SIZE + - REACT_GUTTER_SIZE) - - offsetY; - - let height = REACT_WORK_SIZE - REACT_WORK_DEPTH_OFFSET * depth; + y = baseY + REACT_WORK_SIZE * depth + REACT_GUTTER_SIZE * depth - offsetY; const lineWidth = Math.floor(REACT_EVENT_BORDER_SIZE); - if (depth > 0) { - context.fillStyle = COLORS.REACT_WORK_BORDER; - context.fillRect( - Math.floor(x), - Math.floor(y), - Math.floor(width), - Math.floor(height) - ); - - height -= lineWidth; - - if (width > lineWidth * 2) { - width -= lineWidth * 2; - x += lineWidth; - } - } - // $FlowFixMe We know these won't be null context.fillStyle = showHoverHighlight ? hoveredFillStyle @@ -357,7 +331,7 @@ const renderReact = ({ Math.floor(x), Math.floor(y), Math.floor(width), - Math.floor(height) + REACT_WORK_SIZE ); break; case 'schedule-render': @@ -395,12 +369,7 @@ const renderReact = ({ if (fillStyle !== null) { const circumference = REACT_EVENT_SIZE; - y = - HEADER_HEIGHT_FIXED + - (REACT_DEVTOOLS_PRIORITY_SIZE * priorityIndex + - REACT_GUTTER_SIZE + - REACT_EVENT_SIZE / 2) - - offsetY; + y = baseY + REACT_EVENT_SIZE / 2 - offsetY; context.beginPath(); context.fillStyle = fillStyle; @@ -456,6 +425,7 @@ const renderCanvas = memoize( canvas, canvasWidth, canvasHeight, + schedulerCanvasHeight, state, hoveredEvent ) => { @@ -484,21 +454,47 @@ const renderCanvas = memoize( // Time markers do not scroll off screen; they are always rendered at a fixed vertical position. y = HEADER_HEIGHT_FIXED - offsetY; + let priorityMinY = HEADER_HEIGHT_FIXED; + REACT_PRIORITIES.forEach((priority, priorityIndex) => { const currentPriority = data[priority]; - currentPriority.events.forEach(event => { - const showHoverHighlight = - hoveredEvent && hoveredEvent.event === event; - renderReact({ - canvasWidth, - context, - eventOrMeasure: event, - showGroupHighlight: false, - showHoverHighlight, - priorityIndex, - state, + + let baseY = priorityMinY + REACT_GUTTER_SIZE; + + if (currentPriority.events.length > 0) { + currentPriority.events.forEach(event => { + const showHoverHighlight = + hoveredEvent && hoveredEvent.event === event; + renderReact({ + baseY, + canvasWidth, + context, + eventOrMeasure: event, + showGroupHighlight: false, + showHoverHighlight, + priorityIndex, + state, + }); }); - }); + + // Draw the hovered and/or selected items on top so they stand out. + // This is helpful if there are multiple (overlapping) items close to each other. + if (hoveredEvent !== null && hoveredEvent.event !== null) { + renderReact({ + baseY, + canvasWidth, + context, + eventOrMeasure: hoveredEvent.event, + showGroupHighlight: false, + showHoverHighlight: true, + priorityIndex: hoveredEvent.priorityIndex, + state, + }); + } + + baseY += REACT_EVENT_SIZE + REACT_GUTTER_SIZE; + } + currentPriority.measures.forEach(measure => { const showHoverHighlight = hoveredEvent && hoveredEvent.measure === measure; @@ -507,6 +503,7 @@ const renderCanvas = memoize( hoveredEvent.measure !== null && hoveredEvent.measure.batchUID === measure.batchUID; renderReact({ + baseY, canvasWidth, context, eventOrMeasure: measure, @@ -517,19 +514,7 @@ const renderCanvas = memoize( }); }); - // Draw the hovered and/or selected items on top so they stand out. - // This is helpful if there are multiple (overlapping) items close to each other. - if (hoveredEvent !== null && hoveredEvent.event !== null) { - renderReact({ - canvasWidth, - context, - eventOrMeasure: hoveredEvent.event, - showGroupHighlight: false, - showHoverHighlight: true, - priorityIndex: hoveredEvent.priorityIndex, - state, - }); - } + priorityMinY += getPriorityHeight(data, priority); }); } @@ -545,7 +530,7 @@ const renderCanvas = memoize( const y = Math.floor( HEADER_HEIGHT_FIXED + - REACT_DEVTOOLS_CANVAS_HEIGHT + + schedulerCanvasHeight + i * FLAMECHART_FRAME_HEIGHT - offsetY ); @@ -609,18 +594,24 @@ const renderCanvas = memoize( y = HEADER_HEIGHT_FIXED - offsetY; REACT_PRIORITIES.forEach((priority, priorityIndex) => { + const priorityHeight = getPriorityHeight(data, priority); + + if (priorityHeight === 0) { + return; + } + context.fillStyle = COLORS.PRIORITY_BACKGROUND; context.fillRect( 0, Math.floor(y), Math.floor(LABEL_FIXED_WIDTH), - REACT_DEVTOOLS_PRIORITY_SIZE + priorityHeight ); context.fillStyle = COLORS.PRIORITY_BORDER; context.fillRect( 0, - Math.floor(y + REACT_DEVTOOLS_PRIORITY_SIZE), + Math.floor(y + priorityHeight), canvasWidth, REACT_PRIORITY_BORDER_SIZE ); @@ -630,16 +621,16 @@ const renderCanvas = memoize( Math.floor(LABEL_FIXED_WIDTH) - REACT_PRIORITY_BORDER_SIZE, Math.floor(y), REACT_PRIORITY_BORDER_SIZE, - REACT_DEVTOOLS_PRIORITY_SIZE + priorityHeight ); context.fillStyle = COLORS.PRIORITY_LABEL; context.textAlign = 'left'; context.textBaseline = 'middle'; - context.font = `${REACT_DEVTOOLS_FONT_SIZE}px sans-serif`; - context.fillText(priority, 10, y + REACT_DEVTOOLS_PRIORITY_SIZE / 2); + context.font = `${LABEL_FONT_SIZE}px sans-serif`; + context.fillText(priority, 4, y + priorityHeight / 2); - y += REACT_DEVTOOLS_PRIORITY_SIZE + REACT_PRIORITY_BORDER_SIZE; + y += priorityHeight + REACT_PRIORITY_BORDER_SIZE; }); // TOP: Time markers @@ -690,9 +681,46 @@ const renderCanvas = memoize( } ); +const cachedPriorityHeights = new Map(); +const getPriorityHeight = (data, priority) => { + if (cachedPriorityHeights.has(priority)) { + return cachedPriorityHeights.get(priority); + } else { + const numMeasures = data[priority].maxNestedMeasures; + const events = data[priority].events; + + let priorityHeight = 0; + if (numMeasures > 0 && events.length > 0) { + priorityHeight = + REACT_GUTTER_SIZE + + REACT_EVENT_SIZE + + REACT_WORK_SIZE * numMeasures + + REACT_GUTTER_SIZE * numMeasures + + REACT_PRIORITY_BORDER_SIZE; + } else if (numMeasures > 0) { + priorityHeight = + REACT_GUTTER_SIZE + + REACT_WORK_SIZE * numMeasures + + REACT_GUTTER_SIZE * numMeasures + + REACT_PRIORITY_BORDER_SIZE; + } else if (events.length > 0) { + priorityHeight = + REACT_GUTTER_SIZE + + REACT_EVENT_SIZE + + REACT_GUTTER_SIZE + + REACT_PRIORITY_BORDER_SIZE; + } + + cachedPriorityHeights.set(priority, priorityHeight); + + return priorityHeight; + } +}; + function App() { const [data, setData] = useState(null); const [flamechart, setFlamechart] = useState(null); + const [schedulerCanvasHeight, setSchedulerCanvasHeight] = useState(0); useEffect(() => { fetch(JSON_PATH) @@ -707,11 +735,17 @@ function App() { unstable_batchedUpdates(() => { const processedData = preprocessData(data); setData(processedData); - console.log(data); - console.log(processedData); const flamechart = preprocessFlamechart(data); setFlamechart(flamechart); + + let height = 0; + + REACT_PRIORITIES.forEach(priority => { + height += getPriorityHeight(processedData, priority); + }); + + setSchedulerCanvasHeight(height); }); } }); @@ -725,6 +759,7 @@ function App() { data={data} flamechart={flamechart} height={height} + schedulerCanvasHeight={schedulerCanvasHeight} width={width} /> )} @@ -755,7 +790,13 @@ const zoomToBatch = (data, measure, state) => { state.zoomTo(startTime, stopTime); }; -function AutoSizedCanvas({ data, flamechart, height, width }) { +function AutoSizedCanvas({ + data, + flamechart, + height, + schedulerCanvasHeight, + width, +}) { const canvasRef = useRef(); const state = usePanAndZoom({ @@ -767,12 +808,17 @@ function AutoSizedCanvas({ data, flamechart, height, width }) { unscaledContentWidth: data != null ? data.duration : 0, unscaledContentHeight: data != null - ? REACT_DEVTOOLS_CANVAS_HEIGHT + + ? schedulerCanvasHeight + flamechart.layers.length * FLAMECHART_FRAME_HEIGHT : 0, }); - const hoveredEvent = getHoveredEvent(data, flamechart, state); + const hoveredEvent = getHoveredEvent( + schedulerCanvasHeight, + data, + flamechart, + state + ); const [isContextMenuShown, setIsContextMenuShown] = useState(false); useContextMenu({ @@ -788,15 +834,18 @@ function AutoSizedCanvas({ data, flamechart, height, width }) { }); useLayoutEffect(() => { - renderCanvas( - data, - flamechart, - canvasRef.current, - width, - height, - state, - hoveredEvent - ); + if (data !== null) { + renderCanvas( + data, + flamechart, + canvasRef.current, + width, + height, + schedulerCanvasHeight, + state, + hoveredEvent + ); + } }); return ( diff --git a/src/constants.js b/src/constants.js index 4cdb676488c27..6a294d5b39445 100644 --- a/src/constants.js +++ b/src/constants.js @@ -1,5 +1,5 @@ -export const LABEL_SIZE = 120; -export const LABEL_FONT_SIZE = 14; +export const LABEL_SIZE = 80; +export const LABEL_FONT_SIZE = 11; export const MARKER_HEIGHT = 20; export const MARKER_TICK_HEIGHT = 8; export const MARKER_FONT_SIZE = 10; diff --git a/src/preprocessData.js b/src/preprocessData.js index 093f8e1ebff44..60e40f6d500a7 100644 --- a/src/preprocessData.js +++ b/src/preprocessData.js @@ -24,18 +24,22 @@ export default function reactProfilerProcessor( high: { events: [], measures: [], + maxNestedMeasures: 0, }, normal: { events: [], measures: [], + maxNestedMeasures: 0, }, low: { events: [], measures: [], + maxNestedMeasures: 0, }, unscheduled: { events: [], measures: [], + maxNestedMeasures: 0, }, }; @@ -46,23 +50,23 @@ export default function reactProfilerProcessor( const metadata = { high: { - nextRenderShouldGenerateNewBatchID: true, batchUID: 0, + nextRenderShouldGenerateNewBatchID: true, stack: [], }, normal: { - nextRenderShouldGenerateNewBatchID: true, batchUID: 0, + nextRenderShouldGenerateNewBatchID: true, stack: [], }, low: { - nextRenderShouldGenerateNewBatchID: true, batchUID: 0, + nextRenderShouldGenerateNewBatchID: true, stack: [], }, unscheduled: { - nextRenderShouldGenerateNewBatchID: true, batchUID: 0, + nextRenderShouldGenerateNewBatchID: true, stack: [], }, }; @@ -121,6 +125,11 @@ export default function reactProfilerProcessor( const index = currentProfilerDataGroup.measures.length; const depth = getDepth(); + currentProfilerDataGroup.maxNestedMeasures = Math.max( + currentProfilerDataGroup.maxNestedMeasures, + depth + 1 + ); + stack.push({ depth, index, @@ -226,7 +235,6 @@ export default function reactProfilerProcessor( name === '--layout-effects-start' ? 'layout-effects' : 'passive-effects'; - //throwIfIncomplete(type); markWorkStarted(type, startTime); } else if ( name === '--layout-effects-stop' || diff --git a/src/types.js b/src/types.js index 17fb1e9f53e42..442b590e083e6 100644 --- a/src/types.js +++ b/src/types.js @@ -39,6 +39,7 @@ export type ReactMeasure = {| export type ReactProfilerDataPriority = {| events: Array, measures: Array, + maxNestedMeasures: number, |}; export type ReactProfilerData = {| From 831357b00c4f01265275ac76523f76f452e9a62b Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Mon, 15 Jun 2020 18:09:02 +0800 Subject: [PATCH 007/116] Upgrade dependencies --- package.json | 10 +++--- yarn.lock | 95 +++++++++++++++++++++++++++++----------------------- 2 files changed, 58 insertions(+), 47 deletions(-) diff --git a/package.json b/package.json index 974231af3c9e4..57bf8f995f6b7 100644 --- a/package.json +++ b/package.json @@ -14,15 +14,15 @@ "d3-hierarchy": "^1.1.9", "lodash.clonedeep": "^4.5.0", "memoize-one": "^5.1.1", - "pretty-ms": "^5.1.0", - "react": "^16.12.0", - "react-dom": "^16.12.0", + "pretty-ms": "^7.0.0", + "react": "^16.13.1", + "react-dom": "^16.13.1", "react-virtualized-auto-sizer": "^1.0.2", - "scheduler": "^0.18.0" + "scheduler": "^0.19.1" }, "devDependencies": { "parcel": "2.0.0-alpha.3.2", - "postcss-modules": "^1.4.1", + "postcss-modules": "^2.0.0", "prettier": "^1.19.1" } } diff --git a/yarn.lock b/yarn.lock index 76e98779e9ccf..b73f0c6cd26ef 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1688,10 +1688,10 @@ bcrypt-pbkdf@^1.0.0: dependencies: tweetnacl "^0.14.3" -big.js@^3.1.3: - version "3.2.0" - resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e" - integrity sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q== +big.js@^5.2.2: + version "5.2.2" + resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" + integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== bindings@^1.5.0: version "1.5.0" @@ -2716,10 +2716,10 @@ emoji-regex@^8.0.0: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== -emojis-list@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" - integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k= +emojis-list@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" + integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== emphasize@^2.1.0: version "2.1.0" @@ -3093,12 +3093,12 @@ gauge@~2.7.3: strip-ansi "^3.0.1" wide-align "^1.1.0" -generic-names@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/generic-names/-/generic-names-1.0.3.tgz#2d786a121aee508876796939e8e3bff836c20917" - integrity sha1-LXhqEhruUIh2eWk56OO/+DbCCRc= +generic-names@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/generic-names/-/generic-names-2.0.1.tgz#f8a378ead2ccaa7a34f0317b05554832ae41b872" + integrity sha512-kPCHWa1m9wGG/OwQpeweTwM/PYiQLrUIxXbt/P4Nic3LbGjCP0YwrALHW1uNLKZ0LIMg+RF+XRlj2ekT9ZlZAQ== dependencies: - loader-utils "^0.2.16" + loader-utils "^1.1.0" get-caller-file@^2.0.1: version "2.0.5" @@ -3816,11 +3816,6 @@ json-stringify-safe@~5.0.1: resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= -json5@^0.5.0: - version "0.5.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" - integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE= - json5@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" @@ -3877,15 +3872,14 @@ levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" -loader-utils@^0.2.16: - version "0.2.17" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.17.tgz#f86e6374d43205a6e6c60e9196f17c0299bfb348" - integrity sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g= +loader-utils@^1.1.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" + integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA== dependencies: - big.js "^3.1.3" - emojis-list "^2.0.0" - json5 "^0.5.0" - object-assign "^4.0.1" + big.js "^5.2.2" + emojis-list "^3.0.0" + json5 "^1.0.1" locate-path@^3.0.0: version "3.0.0" @@ -4286,7 +4280,7 @@ oauth-sign@~0.9.0: resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: +object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= @@ -4723,13 +4717,13 @@ postcss-modules-values@1.3.0: icss-replace-symbols "^1.1.0" postcss "^6.0.1" -postcss-modules@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/postcss-modules/-/postcss-modules-1.4.1.tgz#8aa35bd3461db67e27377a7ce770d77b654a84ef" - integrity sha512-btTrbK+Xc3NBuYF8TPBjCMRSp5h6NoQ1iVZ6WiDQENIze6KIYCSf0+UFQuV3yJ7gRHA+4AAtF8i2jRvUpbBMMg== +postcss-modules@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules/-/postcss-modules-2.0.0.tgz#473d0d7326651d8408585c2a154115d5cb36cce0" + integrity sha512-eqp+Bva+U2cwQO7dECJ8/V+X+uH1HduNeITB0CPPFAu6d/8LKQ32/j+p9rQ2YL1QytVcrNU0X+fBqgGmQIA1Rw== dependencies: css-modules-loader-core "^1.1.0" - generic-names "^1.0.3" + generic-names "^2.0.1" lodash.camelcase "^4.3.0" postcss "^7.0.1" string-hash "^1.1.1" @@ -4981,10 +4975,10 @@ prettier@^1.19.1: resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb" integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew== -pretty-ms@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/pretty-ms/-/pretty-ms-5.1.0.tgz#b906bdd1ec9e9799995c372e2b1c34f073f95384" - integrity sha512-4gaK1skD2gwscCfkswYQRmddUb2GJZtzDGRjHWadVHtK/DIKFufa12MvES6/xu1tVbUYeia5bmLcwJtZJQUqnw== +pretty-ms@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/pretty-ms/-/pretty-ms-7.0.0.tgz#45781273110caf35f55cab21a8a9bd403a233dc0" + integrity sha512-J3aPWiC5e9ZeZFuSeBraGxSkGMOvulSWsxDByOcbD1Pr75YL3LSNIKIb52WXbCLE1sS5s4inBBbryjF4Y05Ceg== dependencies: parse-ms "^2.1.0" @@ -5126,15 +5120,15 @@ rc@^1.2.7: minimist "^1.2.0" strip-json-comments "~2.0.1" -react-dom@^16.12.0: - version "16.12.0" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.12.0.tgz#0da4b714b8d13c2038c9396b54a92baea633fe11" - integrity sha512-LMxFfAGrcS3kETtQaCkTKjMiifahaMySFDn71fZUNpPHZQEzmk/GiAeIT8JSOrHB23fnuCOMruL2a8NYlw+8Gw== +react-dom@^16.13.1: + version "16.13.1" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.13.1.tgz#c1bd37331a0486c078ee54c4740720993b2e0e7f" + integrity sha512-81PIMmVLnCNLO/fFOQxdQkvEq/+Hfpv24XNJfpyZhTRfO0QcmQIF/PgCa1zCOj2w1hrn12MFLyaJ/G0+Mxtfag== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" prop-types "^15.6.2" - scheduler "^0.18.0" + scheduler "^0.19.1" react-is@^16.8.1: version "16.12.0" @@ -5161,7 +5155,16 @@ react-virtualized-auto-sizer@^1.0.2: resolved "https://registry.yarnpkg.com/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.2.tgz#a61dd4f756458bbf63bd895a92379f9b70f803bd" integrity sha512-MYXhTY1BZpdJFjUovvYHVBmkq79szK/k7V3MO+36gJkWGkrXKtyr4vCPtpphaTLRAdDNoYEYFZWE8LjN+PIHNg== -react@^16.12.0, react@^16.7.0: +react@^16.13.1: + version "16.13.1" + resolved "https://registry.yarnpkg.com/react/-/react-16.13.1.tgz#2e818822f1a9743122c063d6410d85c1e3afe48e" + integrity sha512-YMZQQq32xHLX0bz5Mnibv1/LHb3Sqzngu7xstSM+vrkE5Kzr9xE0yMByK5kMoTK30YVJE61WfbxIFFvfeDKT1w== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + prop-types "^15.6.2" + +react@^16.7.0: version "16.12.0" resolved "https://registry.yarnpkg.com/react/-/react-16.12.0.tgz#0c0a9c6a142429e3614834d5a778e18aa78a0b83" integrity sha512-fglqy3k5E+81pA8s+7K0/T3DBCF0ZDOher1elBFzF7O6arXJgzyu/FW+COxFvAWXJoJN9KIZbT2LXlukwphYTA== @@ -5458,6 +5461,14 @@ scheduler@^0.18.0: loose-envify "^1.1.0" object-assign "^4.1.1" +scheduler@^0.19.1: + version "0.19.1" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.19.1.tgz#4f3e2ed2c1a7d65681f4c854fa8c5a1ccb40f196" + integrity sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + semver@7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" From 240f9d3bbce27ee2ed653bfb21c51cf597262134 Mon Sep 17 00:00:00 2001 From: Kartik Choudhary Date: Mon, 15 Jun 2020 20:11:28 +0530 Subject: [PATCH 008/116] Disable caching to fix tooltip bugs --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 57bf8f995f6b7..c028f60eafb4f 100644 --- a/package.json +++ b/package.json @@ -2,9 +2,9 @@ "name": "scheduling-profiler-prototype", "version": "0.0.1", "scripts": { - "build": "parcel build index.html", + "build": "parcel build index.html --no-cache", "prettier": "prettier --write '**/*.{js,json,css}'", - "start": "parcel index.html" + "start": "parcel index.html --no-cache" }, "author": "Brian Vaughn ", "license": "MIT", From 8260bdcf3e585424cfd781839d1b9b937c785a88 Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Tue, 16 Jun 2020 13:24:11 +0800 Subject: [PATCH 009/116] Enable Flow in VS Code by adding flow-bin, .flowconfig and VS code settings --- .flowconfig | 11 +++++++++++ .vscode/settings.json | 3 +++ package.json | 1 + yarn.lock | 5 +++++ 4 files changed, 20 insertions(+) create mode 100644 .flowconfig create mode 100644 .vscode/settings.json diff --git a/.flowconfig b/.flowconfig new file mode 100644 index 0000000000000..1fed445333e85 --- /dev/null +++ b/.flowconfig @@ -0,0 +1,11 @@ +[ignore] + +[include] + +[libs] + +[lints] + +[options] + +[strict] diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000000000..f9a4c68002704 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "javascript.validate.enable": false +} diff --git a/package.json b/package.json index c028f60eafb4f..30a3875b03642 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "scheduler": "^0.19.1" }, "devDependencies": { + "flow-bin": "^0.127.0", "parcel": "2.0.0-alpha.3.2", "postcss-modules": "^2.0.0", "prettier": "^1.19.1" diff --git a/yarn.lock b/yarn.lock index b73f0c6cd26ef..ac24575e933b4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3021,6 +3021,11 @@ find-up@^3.0.0: dependencies: locate-path "^3.0.0" +flow-bin@^0.127.0: + version "0.127.0" + resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.127.0.tgz#0614cff4c1b783beef1feeb7108d536e09d77632" + integrity sha512-ywvCCdV4NJWzrqjFrMU5tAiVGyBiXjsJQ1+/kj8thXyX15V17x8BFvNwoAH97NrUU8T1HzmFBjLzWc0l2319qg== + follow-redirects@^1.0.0: version "1.9.0" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.9.0.tgz#8d5bcdc65b7108fe1508649c79c12d732dcedb4f" From 63af3265aa8cd8d727587c70d6a53dd0b5f1ac88 Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Tue, 16 Jun 2020 22:12:21 +0800 Subject: [PATCH 010/116] Add type annotations (1/n) (#7) --- src/App.js | 15 +- src/canvasUtils.js | 22 +- src/constants.js | 2 + src/context/ContextMenu.js | 28 +- src/context/ContextMenuItem.js | 2 +- src/context/Contexts.js | 15 +- src/context/useContextMenu.js | 22 +- src/contexts.js | 10 +- src/preprocessData.js | 15 +- src/preprocessFlamechart.js | 3 +- src/speedscope/import/chrome.js | 449 +++++++------ src/speedscope/lib/flamechart.js | 224 ++++--- src/speedscope/lib/profile.js | 1062 ++++++++++++++++-------------- src/types.js | 4 +- src/useDebounce.js | 54 +- src/useInteractiveEvents.js | 2 + src/usePanAndZoom.js | 153 +++-- src/utils.js | 2 +- 18 files changed, 1209 insertions(+), 875 deletions(-) diff --git a/src/App.js b/src/App.js index 00b0ff3091755..069dafb8ea53f 100644 --- a/src/App.js +++ b/src/App.js @@ -1,5 +1,7 @@ // @flow +import type { TimelineEvent } from './speedscope/import/chrome'; + import { copy } from 'clipboard-js'; import React, { Fragment, @@ -725,7 +727,7 @@ function App() { useEffect(() => { fetch(JSON_PATH) .then(data => data.json()) - .then(data => { + .then((data: TimelineEvent[]) => { // Filter null entries and sort by timestamp. // I would not expect to have to do either of this, // but some of the data being passed in requires it. @@ -790,14 +792,21 @@ const zoomToBatch = (data, measure, state) => { state.zoomTo(startTime, stopTime); }; +type Props = {| + data: any, // TODO: Fix + flamechart: FlamechartData, + height: number, + schedulerCanvasHeight: number, + width: number, +|}; function AutoSizedCanvas({ data, flamechart, height, schedulerCanvasHeight, width, -}) { - const canvasRef = useRef(); +}: Props) { + const canvasRef = useRef(null); const state = usePanAndZoom({ canvasRef, diff --git a/src/canvasUtils.js b/src/canvasUtils.js index b4b39fbc8e38c..ddaba9a3bf140 100644 --- a/src/canvasUtils.js +++ b/src/canvasUtils.js @@ -1,8 +1,14 @@ +// @flow + import memoize from 'memoize-one'; // hidpi canvas: https://www.html5rocks.com/en/tutorials/canvas/hidpi/ -export function configureRetinaCanvas(canvas, height, width) { - const dpr = window.devicePixelRatio || 1; +export function configureRetinaCanvas( + canvas: HTMLCanvasElement, + height: number, + width: number +): number { + const dpr: number = window.devicePixelRatio || 1; canvas.width = width * dpr; canvas.height = height * dpr; canvas.style.width = `${width}px`; @@ -11,7 +17,12 @@ export function configureRetinaCanvas(canvas, height, width) { } export const getCanvasContext = memoize( - (canvas, height, width, scaleCanvas = true) => { + ( + canvas: HTMLCanvasElement, + height: number, + width: number, + scaleCanvas: boolean = true + ): CanvasRenderingContext2D => { const context = canvas.getContext('2d', { alpha: false }); if (scaleCanvas) { const dpr = configureRetinaCanvas(canvas, height, width); @@ -22,7 +33,10 @@ export const getCanvasContext = memoize( } ); -export function getCanvasMousePos(canvas, mouseEvent) { +export function getCanvasMousePos( + canvas: HTMLCanvasElement, + mouseEvent: MouseEvent +) { const rect = canvas instanceof HTMLCanvasElement ? canvas.getBoundingClientRect() diff --git a/src/constants.js b/src/constants.js index 6a294d5b39445..4db22538d2e98 100644 --- a/src/constants.js +++ b/src/constants.js @@ -1,3 +1,5 @@ +// @flow + export const LABEL_SIZE = 80; export const LABEL_FONT_SIZE = 11; export const MARKER_HEIGHT = 20; diff --git a/src/context/ContextMenu.js b/src/context/ContextMenu.js index aa176f62f6a32..72c64f42e1d9c 100644 --- a/src/context/ContextMenu.js +++ b/src/context/ContextMenu.js @@ -54,18 +54,25 @@ export default function ContextMenu({ children, id }: Props) { const [state, setState] = useState(HIDDEN_STATE); - const bodyAccessorRef = useRef(null); - const containerRef = useRef(null); - const menuRef = useRef(null); + const bodyAccessorRef = useRef(null); + const containerRef = useRef(null); + const menuRef = useRef(null); useEffect(() => { + if (!bodyAccessorRef.current) { + return; + } const ownerDocument = bodyAccessorRef.current.ownerDocument; containerRef.current = ownerDocument.createElement('div'); - ownerDocument.body.appendChild(containerRef.current); + if (ownerDocument.body) { + ownerDocument.body.appendChild(containerRef.current); + } return () => { - ownerDocument.body.removeChild(containerRef.current); + if (ownerDocument.body && containerRef.current) { + ownerDocument.body.removeChild(containerRef.current); + } }; - }, []); + }, [bodyAccessorRef, containerRef]); useEffect(() => { const showMenu = ({ data, pageX, pageY }) => { @@ -76,13 +83,18 @@ export default function ContextMenu({ children, id }: Props) { }, [id]); useLayoutEffect(() => { - if (!state.isVisible) { + if (!state.isVisible || !containerRef.current) { return; } const menu = menuRef.current; + if (!menu) { + return; + } - const hideUnlessContains = event => { + const hideUnlessContains: MouseEventHandler & + TouchEventHandler & + KeyboardEventHandler = event => { if (!menu.contains(event.target)) { hideMenu(); } diff --git a/src/context/ContextMenuItem.js b/src/context/ContextMenuItem.js index 90d3b4b79fb27..20a89f7e4ab66 100644 --- a/src/context/ContextMenuItem.js +++ b/src/context/ContextMenuItem.js @@ -14,7 +14,7 @@ type Props = {| export default function ContextMenuItem({ children, onClick, title }: Props) { const { hideMenu } = useContext(RegistryContext); - const handleClick = event => { + const handleClick: MouseEventHandler = event => { onClick(); hideMenu(); }; diff --git a/src/context/Contexts.js b/src/context/Contexts.js index c0803051ab7db..43618402da777 100644 --- a/src/context/Contexts.js +++ b/src/context/Contexts.js @@ -4,12 +4,13 @@ import { createContext } from 'react'; export type ShowFn = ({| data: Object, pageX: number, pageY: number |}) => void; export type HideFn = () => void; +export type OnChangeFn = boolean => void; const idToShowFnMap = new Map(); const idToHideFnMap = new Map(); -let currentHideFn = null; -let currentOnChange = null; +let currentHideFn: ?HideFn = null; +let currentOnChange: ?OnChangeFn = null; function hideMenu() { if (typeof currentHideFn === 'function') { @@ -33,7 +34,7 @@ function showMenu({ }: {| data: Object, id: string, - onChange?: Function, + onChange?: OnChangeFn, pageX: number, pageY: number, |}) { @@ -63,7 +64,13 @@ function registerMenu(id: string, showFn: ShowFn, hideFn: HideFn) { }; } -export const RegistryContext = createContext({ +type ContextMenuContext = {| + hideMenu: typeof hideMenu, + showMenu: typeof showMenu, + registerMenu: typeof registerMenu, +|}; + +export const RegistryContext = createContext({ hideMenu, showMenu, registerMenu, diff --git a/src/context/useContextMenu.js b/src/context/useContextMenu.js index 6acb9e86b3eae..3b2e3d2079ebe 100644 --- a/src/context/useContextMenu.js +++ b/src/context/useContextMenu.js @@ -4,6 +4,7 @@ import { useContext, useEffect } from 'react'; import { RegistryContext } from './Contexts'; import type { ElementRef } from 'react'; +import type { OnChangeFn } from './Contexts'; export default function useContextMenu({ data, @@ -11,29 +12,36 @@ export default function useContextMenu({ onChange, ref, }: {| - data: Object, + data: Object, // TODO: Type this? id: string, - ref: ElementRef, + onChange: OnChangeFn, + ref: {| current: HTMLElement | null |}, |}) { const { showMenu } = useContext(RegistryContext); useEffect(() => { if (ref.current !== null) { - const handleContextMenu = event => { + const handleContextMenu: MouseEventHandler = event => { event.preventDefault(); event.stopPropagation(); - const pageX = event.pageX || (event.touches && event.touches[0].pageX); - const pageY = event.pageY || (event.touches && event.touches[0].pageY); + const pageX: number = + event.pageX || (event.touches && event.touches[0].pageX); + const pageY: number = + event.pageY || (event.touches && event.touches[0].pageY); showMenu({ data, id, onChange, pageX, pageY }); }; const trigger = ref.current; - trigger.addEventListener('contextmenu', handleContextMenu); + if (trigger) { + trigger.addEventListener('contextmenu', handleContextMenu); + } return () => { - trigger.removeEventListener('contextmenu', handleContextMenu); + if (trigger) { + trigger.removeEventListener('contextmenu', handleContextMenu); + } }; } }, [data, id, showMenu]); diff --git a/src/contexts.js b/src/contexts.js index 4c2bd2abe796b..7452ff4a780b0 100644 --- a/src/contexts.js +++ b/src/contexts.js @@ -1,4 +1,8 @@ -import { createContext } from 'react'; +// @flow -export const PriorityContext = createContext(null); -export const TimeRangeContext = createContext([0, 0]); +// import { createContext } from 'react'; + +// TODO: Figure out what these contexts are for. They were added in the +// prototype but were unused. +// export const PriorityContext = createContext(null); +// export const TimeRangeContext = createContext([0, 0]); diff --git a/src/preprocessData.js b/src/preprocessData.js index 60e40f6d500a7..7b8c3c8397873 100644 --- a/src/preprocessData.js +++ b/src/preprocessData.js @@ -1,5 +1,7 @@ // @flow +import type { TimelineEvent } from './speedscope/import/chrome'; + import type { BatchUID, ReactPriority, @@ -16,7 +18,7 @@ type Metadata = {| |}; export default function reactProfilerProcessor( - rawData: Array + rawData: TimelineEvent[] ): ReactProfilerData { const reactProfilerData = { startTime: rawData[0].ts, @@ -43,7 +45,7 @@ export default function reactProfilerProcessor( }, }; - let currentMetadata = null; + let currentMetadata: ?Metadata = null; let currentPriority = 'unscheduled'; let currentProfilerDataGroup = null; let uidCounter = 0; @@ -72,6 +74,9 @@ export default function reactProfilerProcessor( }; const getLastType = () => { + if (!currentMetadata) { + return null; + } const { stack } = currentMetadata; if (stack.length > 0) { const { type } = stack[stack.length - 1]; @@ -81,6 +86,9 @@ export default function reactProfilerProcessor( }; const getDepth = () => { + if (!currentMetadata) { + return 0; + } const { stack } = currentMetadata; if (stack.length > 0) { const { depth, type } = stack[stack.length - 1]; @@ -90,6 +98,9 @@ export default function reactProfilerProcessor( }; const markWorkCompleted = (type, stopTime) => { + if (!currentMetadata) { + return; + } const { stack } = currentMetadata; if (stack.length === 0) { console.error( diff --git a/src/preprocessFlamechart.js b/src/preprocessFlamechart.js index de2e4c0c2b5f1..87e81533a3f8d 100644 --- a/src/preprocessFlamechart.js +++ b/src/preprocessFlamechart.js @@ -3,10 +3,11 @@ import { importFromChromeTimeline } from './speedscope/import/chrome'; import { Flamechart } from './speedscope/lib/flamechart'; +import type { TimelineEvent } from './speedscope/import/chrome'; import type { FlamechartData } from './types'; export default function preprocessFlamechart( - rawData: Array + rawData: TimelineEvent[] ): FlamechartData { const parsedData = importFromChromeTimeline(rawData, 'react-devtools'); const profile = parsedData.profiles[0]; // TODO Choose the main CPU thread only diff --git a/src/speedscope/import/chrome.js b/src/speedscope/import/chrome.js index 0ba96ab8d167c..f79c0df3ed918 100644 --- a/src/speedscope/import/chrome.js +++ b/src/speedscope/import/chrome.js @@ -1,228 +1,275 @@ -import {Profile, FrameInfo, CallTreeProfileBuilder, ProfileGroup} from '../lib/profile' -import {getOrInsert, lastOf, sortBy, itForEach} from '../lib/utils' -import {TimeFormatter} from '../lib/value-formatters' -import {chromeTreeToNodes, OldCPUProfile} from './v8cpuFormatter' +// @flow + +import { + Profile, + FrameInfo, + CallTreeProfileBuilder, + ProfileGroup, +} from '../lib/profile'; +import { getOrInsert, lastOf, sortBy, itForEach } from '../lib/utils'; +import { TimeFormatter } from '../lib/value-formatters'; +import { chromeTreeToNodes, OldCPUProfile } from './v8cpuFormatter'; // See: https://github.com/v8/v8/blob/master/src/inspector/js_protocol.json +export interface TimelineEvent { + pid: number; + tid: number; + ts: number; + ph: string; + cat: string; + name: string; + dur: number; + tdur: number; + tts: number; + args: { [key: string]: any }; + id?: String; +} + export function isChromeTimeline(rawProfile) { - if (!Array.isArray(rawProfile)) - return false; - if (rawProfile.length < 1) - return false; - const first = rawProfile[0]; - if (!('pid' in first && 'tid' in first && 'ph' in first && 'cat' in first)) - return false; - if (!rawProfile.find(e => e.name === 'CpuProfile' || e.name === 'Profile' || e.name === 'ProfileChunk')) - return false; - return true; + if (!Array.isArray(rawProfile)) return false; + if (rawProfile.length < 1) return false; + const first = rawProfile[0]; + if (!('pid' in first && 'tid' in first && 'ph' in first && 'cat' in first)) + return false; + if ( + !rawProfile.find( + e => + e.name === 'CpuProfile' || + e.name === 'Profile' || + e.name === 'ProfileChunk' + ) + ) + return false; + return true; } -export function importFromChromeTimeline(events, fileName) { - // It seems like sometimes Chrome timeline files contain multiple CpuProfiles? - // For now, choose the first one in the list. - const cpuProfileByID = new Map(); - // Maps profile IDs (like "0x3") to pid/tid pairs formatted as `${pid}:${tid}` - const pidTidById = new Map(); - // Maps pid/tid pairs to thread names - const threadNameByPidTid = new Map(); - // The events aren't necessarily recorded in chronological order. Sort them so - // that they are. - sortBy(events, e => e.ts); - for (let event of events) { - if (event.name === 'CpuProfile') { - const pidTid = `${event.pid}:${event.tid}`; - const id = event.id || pidTid; - cpuProfileByID.set(id, event.args.data.cpuProfile); - pidTidById.set(id, pidTid); +export function importFromChromeTimeline( + events: TimelineEvent[], + fileName: string +): ProfileGroup { + // It seems like sometimes Chrome timeline files contain multiple CpuProfiles? + // For now, choose the first one in the list. + const cpuProfileByID = new Map(); + // Maps profile IDs (like "0x3") to pid/tid pairs formatted as `${pid}:${tid}` + const pidTidById = new Map(); + // Maps pid/tid pairs to thread names + const threadNameByPidTid = new Map(); + // The events aren't necessarily recorded in chronological order. Sort them so + // that they are. + sortBy(events, e => e.ts); + for (let event of events) { + if (event.name === 'CpuProfile') { + const pidTid = `${event.pid}:${event.tid}`; + const id = event.id || pidTid; + cpuProfileByID.set(id, event.args.data.cpuProfile); + pidTidById.set(id, pidTid); + } + if (event.name === 'Profile') { + const pidTid = `${event.pid}:${event.tid}`; + cpuProfileByID.set( + event.id || pidTid, + Object.assign( + { startTime: 0, endTime: 0, nodes: [], samples: [], timeDeltas: [] }, + event.args.data + ) + ); + if (event.id) { + pidTidById.set(event.id, `${event.pid}:${event.tid}`); + } + } + if (event.name === 'thread_name') { + threadNameByPidTid.set(`${event.pid}:${event.tid}`, event.args.name); + } + if (event.name === 'ProfileChunk') { + const pidTid = `${event.pid}:${event.tid}`; + const cpuProfile = cpuProfileByID.get(event.id || pidTid); + if (cpuProfile) { + const chunk = event.args.data; + if (chunk.cpuProfile) { + if (chunk.cpuProfile.nodes) { + cpuProfile.nodes = cpuProfile.nodes.concat(chunk.cpuProfile.nodes); + } + if (chunk.cpuProfile.samples) { + cpuProfile.samples = cpuProfile.samples.concat( + chunk.cpuProfile.samples + ); + } } - if (event.name === 'Profile') { - const pidTid = `${event.pid}:${event.tid}`; - cpuProfileByID.set(event.id || pidTid, Object.assign({ startTime: 0, endTime: 0, nodes: [], samples: [], timeDeltas: [] }, event.args.data)); - if (event.id) { - pidTidById.set(event.id, `${event.pid}:${event.tid}`); - } + if (chunk.timeDeltas) { + cpuProfile.timeDeltas = cpuProfile.timeDeltas.concat( + chunk.timeDeltas + ); } - if (event.name === 'thread_name') { - threadNameByPidTid.set(`${event.pid}:${event.tid}`, event.args.name); + if (chunk.startTime != null) { + cpuProfile.startTime = chunk.startTime; } - if (event.name === 'ProfileChunk') { - const pidTid = `${event.pid}:${event.tid}`; - const cpuProfile = cpuProfileByID.get(event.id || pidTid); - if (cpuProfile) { - const chunk = event.args.data; - if (chunk.cpuProfile) { - if (chunk.cpuProfile.nodes) { - cpuProfile.nodes = cpuProfile.nodes.concat(chunk.cpuProfile.nodes); - } - if (chunk.cpuProfile.samples) { - cpuProfile.samples = cpuProfile.samples.concat(chunk.cpuProfile.samples); - } - } - if (chunk.timeDeltas) { - cpuProfile.timeDeltas = cpuProfile.timeDeltas.concat(chunk.timeDeltas); - } - if (chunk.startTime != null) { - cpuProfile.startTime = chunk.startTime; - } - if (chunk.endTime != null) { - cpuProfile.endTime = chunk.endTime; - } - } - else { - console.warn(`Ignoring ProfileChunk for undeclared Profile with id ${event.id || pidTid}`); - } + if (chunk.endTime != null) { + cpuProfile.endTime = chunk.endTime; } + } else { + console.warn( + `Ignoring ProfileChunk for undeclared Profile with id ${event.id || + pidTid}` + ); + } } - if (cpuProfileByID.size > 0) { - const profiles = []; - let indexToView = 0; - itForEach(cpuProfileByID.keys(), profileId => { - let threadName = null; - let pidTid = pidTidById.get(profileId); - if (pidTid) { - threadName = threadNameByPidTid.get(pidTid) || null; - if (threadName) { - } - } - const profile = importFromChromeCPUProfile(cpuProfileByID.get(profileId)); - if (threadName && cpuProfileByID.size > 1) { - profile.setName(`${fileName} - ${threadName}`); - if (threadName === 'CrRendererMain') { - indexToView = profiles.length; - } - } - else { - profile.setName(`${fileName}`); - } - profiles.push(profile); - }); - return { name: fileName, indexToView, profiles }; - } - else { - throw new Error('Could not find CPU profile in Timeline'); - } + } + if (cpuProfileByID.size > 0) { + const profiles = []; + let indexToView = 0; + itForEach(cpuProfileByID.keys(), profileId => { + let threadName = null; + let pidTid = pidTidById.get(profileId); + if (pidTid) { + threadName = threadNameByPidTid.get(pidTid) || null; + if (threadName) { + } + } + const profile = importFromChromeCPUProfile(cpuProfileByID.get(profileId)); + if (threadName && cpuProfileByID.size > 1) { + profile.setName(`${fileName} - ${threadName}`); + if (threadName === 'CrRendererMain') { + indexToView = profiles.length; + } + } else { + profile.setName(`${fileName}`); + } + profiles.push(profile); + }); + return { name: fileName, indexToView, profiles }; + } else { + throw new Error('Could not find CPU profile in Timeline'); + } } const callFrameToFrameInfo = new Map(); function frameInfoForCallFrame(callFrame) { - return getOrInsert(callFrameToFrameInfo, callFrame, callFrame => { - const name = callFrame.functionName || '(anonymous)'; - const file = callFrame.url; - const line = callFrame.lineNumber; - const col = callFrame.columnNumber; - return { - key: `${name}:${file}:${line}:${col}`, - name, - file, - line, - col, - }; - }); + return getOrInsert(callFrameToFrameInfo, callFrame, callFrame => { + const name = callFrame.functionName || '(anonymous)'; + const file = callFrame.url; + const line = callFrame.lineNumber; + const col = callFrame.columnNumber; + return { + key: `${name}:${file}:${line}:${col}`, + name, + file, + line, + col, + }; + }); } function shouldIgnoreFunction(callFrame) { - const { functionName, url } = callFrame; - if (url === 'native dummy.js') { - // I'm not really sure what this is about, but this seems to be used - // as a way of avoiding edge cases in V8's implementation. - // See: https://github.com/v8/v8/blob/b8626ca4/tools/js2c.py#L419-L424 - return true; - } - return functionName === '(root)' || functionName === '(idle)'; + const { functionName, url } = callFrame; + if (url === 'native dummy.js') { + // I'm not really sure what this is about, but this seems to be used + // as a way of avoiding edge cases in V8's implementation. + // See: https://github.com/v8/v8/blob/b8626ca4/tools/js2c.py#L419-L424 + return true; + } + return functionName === '(root)' || functionName === '(idle)'; } function shouldPlaceOnTopOfPreviousStack(functionName) { - return functionName === '(garbage collector)' || functionName === '(program)'; + return functionName === '(garbage collector)' || functionName === '(program)'; } export function importFromChromeCPUProfile(chromeProfile) { - const profile = new CallTreeProfileBuilder(chromeProfile.endTime - chromeProfile.startTime); - const nodeById = new Map(); - for (let node of chromeProfile.nodes) { - nodeById.set(node.id, node); + const profile = new CallTreeProfileBuilder( + chromeProfile.endTime - chromeProfile.startTime + ); + const nodeById = new Map(); + for (let node of chromeProfile.nodes) { + nodeById.set(node.id, node); + } + for (let node of chromeProfile.nodes) { + if (typeof node.parent === 'number') { + node.parent = nodeById.get(node.parent); } - for (let node of chromeProfile.nodes) { - if (typeof node.parent === 'number') { - node.parent = nodeById.get(node.parent); - } - if (!node.children) - continue; - for (let childId of node.children) { - const child = nodeById.get(childId); - if (!child) - continue; - child.parent = node; - } + if (!node.children) continue; + for (let childId of node.children) { + const child = nodeById.get(childId); + if (!child) continue; + child.parent = node; } - const samples = []; - const sampleTimes = []; - // The first delta is relative to the profile startTime. - // Ref: https://github.com/v8/v8/blob/44bd8fd7/src/inspector/js_protocol.json#L1485 - let elapsed = chromeProfile.timeDeltas[0]; - let lastNodeId = NaN; - // The chrome CPU profile format doesn't collapse identical samples. We'll do that - // here to save a ton of work later doing mergers. - for (let i = 0; i < chromeProfile.samples.length; i++) { - const nodeId = chromeProfile.samples[i]; - if (nodeId != lastNodeId) { - samples.push(nodeId); - sampleTimes.push(elapsed); - } - if (i === chromeProfile.samples.length - 1) { - if (!isNaN(lastNodeId)) { - samples.push(lastNodeId); - sampleTimes.push(elapsed); - } - } - else { - let timeDelta = chromeProfile.timeDeltas[i + 1]; - if (timeDelta < 0) { - // This is super noisy, but can be helpful when debugging strange data - // console.warn('Substituting zero for unexpected time delta:', timeDelta, 'at index', i) - timeDelta = 0; - } - elapsed += timeDelta; - lastNodeId = nodeId; - } + } + const samples = []; + const sampleTimes = []; + // The first delta is relative to the profile startTime. + // Ref: https://github.com/v8/v8/blob/44bd8fd7/src/inspector/js_protocol.json#L1485 + let elapsed = chromeProfile.timeDeltas[0]; + let lastNodeId = NaN; + // The chrome CPU profile format doesn't collapse identical samples. We'll do that + // here to save a ton of work later doing mergers. + for (let i = 0; i < chromeProfile.samples.length; i++) { + const nodeId = chromeProfile.samples[i]; + if (nodeId != lastNodeId) { + samples.push(nodeId); + sampleTimes.push(elapsed); } - let prevStack = []; - for (let i = 0; i < samples.length; i++) { - const value = sampleTimes[i]; - const nodeId = samples[i]; - let stackTop = nodeById.get(nodeId); - if (!stackTop) - continue; - // Find lowest common ancestor of the current stack and the previous one - let lca = null; - // This is O(n^2), but n should be relatively small here (stack height), - // so hopefully this isn't much of a problem - for (lca = stackTop; lca && prevStack.indexOf(lca) === -1; lca = shouldPlaceOnTopOfPreviousStack(lca.callFrame.functionName) - ? lastOf(prevStack) - : lca.parent || null) { } - // Close frames that are no longer open - while (prevStack.length > 0 && lastOf(prevStack) != lca) { - const closingNode = prevStack.pop(); - const frame = frameInfoForCallFrame(closingNode.callFrame); - profile.leaveFrame(frame, value); - } - // Open frames that are now becoming open - const toOpen = []; - for (let node = stackTop; node && node != lca && !shouldIgnoreFunction(node.callFrame); - // Place Chrome internal functions on top of the previous call stack - node = shouldPlaceOnTopOfPreviousStack(node.callFrame.functionName) - ? lastOf(prevStack) - : node.parent || null) { - toOpen.push(node); - } - toOpen.reverse(); - for (let node of toOpen) { - profile.enterFrame(frameInfoForCallFrame(node.callFrame), value); - } - prevStack = prevStack.concat(toOpen); + if (i === chromeProfile.samples.length - 1) { + if (!isNaN(lastNodeId)) { + samples.push(lastNodeId); + sampleTimes.push(elapsed); + } + } else { + let timeDelta = chromeProfile.timeDeltas[i + 1]; + if (timeDelta < 0) { + // This is super noisy, but can be helpful when debugging strange data + // console.warn('Substituting zero for unexpected time delta:', timeDelta, 'at index', i) + timeDelta = 0; + } + elapsed += timeDelta; + lastNodeId = nodeId; + } + } + let prevStack = []; + for (let i = 0; i < samples.length; i++) { + const value = sampleTimes[i]; + const nodeId = samples[i]; + let stackTop = nodeById.get(nodeId); + if (!stackTop) continue; + // Find lowest common ancestor of the current stack and the previous one + let lca = null; + // This is O(n^2), but n should be relatively small here (stack height), + // so hopefully this isn't much of a problem + for ( + lca = stackTop; + lca && prevStack.indexOf(lca) === -1; + lca = shouldPlaceOnTopOfPreviousStack(lca.callFrame.functionName) + ? lastOf(prevStack) + : lca.parent || null + ) {} + // Close frames that are no longer open + while (prevStack.length > 0 && lastOf(prevStack) != lca) { + const closingNode = prevStack.pop(); + const frame = frameInfoForCallFrame(closingNode.callFrame); + profile.leaveFrame(frame, value); + } + // Open frames that are now becoming open + const toOpen = []; + for ( + let node = stackTop; + node && node != lca && !shouldIgnoreFunction(node.callFrame); + // Place Chrome internal functions on top of the previous call stack + node = shouldPlaceOnTopOfPreviousStack(node.callFrame.functionName) + ? lastOf(prevStack) + : node.parent || null + ) { + toOpen.push(node); } - // Close frames that are open at the end of the trace - for (let i = prevStack.length - 1; i >= 0; i--) { - profile.leaveFrame(frameInfoForCallFrame(prevStack[i].callFrame), lastOf(sampleTimes)); + toOpen.reverse(); + for (let node of toOpen) { + profile.enterFrame(frameInfoForCallFrame(node.callFrame), value); } - profile.setValueFormatter(new TimeFormatter('microseconds')); - return profile.build(); + prevStack = prevStack.concat(toOpen); + } + // Close frames that are open at the end of the trace + for (let i = prevStack.length - 1; i >= 0; i--) { + profile.leaveFrame( + frameInfoForCallFrame(prevStack[i].callFrame), + lastOf(sampleTimes) + ); + } + profile.setValueFormatter(new TimeFormatter('microseconds')); + return profile.build(); } export function importFromOldV8CPUProfile(content) { - return importFromChromeCPUProfile(chromeTreeToNodes(content)); + return importFromChromeCPUProfile(chromeTreeToNodes(content)); } diff --git a/src/speedscope/lib/flamechart.js b/src/speedscope/lib/flamechart.js index d72684eeea2a3..ad22e76fcc53b 100644 --- a/src/speedscope/lib/flamechart.js +++ b/src/speedscope/lib/flamechart.js @@ -1,97 +1,137 @@ +// @flow + +import type { Frame, CallTreeNode } from './profile' + import { lastOf } from './utils'; import { clamp } from './math'; +export interface FlamechartFrame { + node: CallTreeNode; + start: number; + end: number; + parent: FlamechartFrame | null; + children: FlamechartFrame[]; +} + +type StackLayer = FlamechartFrame[]; + +interface FlamechartDataSource { + getTotalWeight(): number; + + formatValue(v: number): string; + + forEachCall( + openFrame: (node: CallTreeNode, value: number) => void, + closeFrame: (node: CallTreeNode, value: number) => void + ): void; + + getColorBucketForFrame(f: Frame): number; +} + export class Flamechart { - constructor(source) { - this.source = source; - // Bottom to top - this.layers = []; - this.totalWeight = 0; - this.minFrameWidth = 1; - const stack = []; - const openFrame = (node, value) => { - const parent = lastOf(stack); - const frame = { - node, - parent, - children: [], - start: value, - end: value, - }; - if (parent) { - parent.children.push(frame); - } - stack.push(frame); - }; - this.minFrameWidth = Infinity; - const closeFrame = (node, value) => { - console.assert(stack.length > 0); - const stackTop = stack.pop(); - stackTop.end = value; - if (stackTop.end - stackTop.start === 0) - return; - const layerIndex = stack.length; - while (this.layers.length <= layerIndex) - this.layers.push([]); - this.layers[layerIndex].push(stackTop); - this.minFrameWidth = Math.min(this.minFrameWidth, stackTop.end - stackTop.start); - }; - this.totalWeight = source.getTotalWeight(); - source.forEachCall(openFrame, closeFrame); - if (!isFinite(this.minFrameWidth)) - this.minFrameWidth = 1; - } - getTotalWeight() { - return this.totalWeight; - } - getLayers() { - return this.layers; - } - getColorBucketForFrame(frame) { - return this.source.getColorBucketForFrame(frame); - } - getMinFrameWidth() { - return this.minFrameWidth; - } - formatValue(v) { - return this.source.formatValue(v); - } - getClampedViewportWidth(viewportWidth) { - const maxWidth = this.getTotalWeight(); - // In order to avoid floating point error, we cap the maximum zoom. In - // particular, it's important that at the maximum zoom level, the total - // trace size + a viewport width is not equal to the trace size due to - // floating point rounding. - // - // For instance, if the profile's total weight is 2^60, and the viewport - // size is 1, trying to move one viewport width right will result in no - // change because 2^60 + 1 = 2^60 in floating point arithmetic. JavaScript - // numbers are 64 bit floats, and therefore have 53 mantissa bits. You can - // see this for yourself in the console. Try: - // - // > Math.pow(2, 60) + 1 === Math.pow(2, 60) - // true - // > Math.pow(2, 53) + 1 === Math.pow(2, 53) - // true - // > Math.pow(2, 52) + 1 === Math.pow(2, 52) - // false - // - // We use 2^40 as a cap instead, since we want to be able to make small - // adjustments within a viewport width. - // - // For reference, this will still allow you to zoom until 1 nanosecond fills - // the screen in a profile with a duration of over 18 minutes. - // - // > Math.pow(2, 40) / (60 * Math.pow(10, 9)) - // 18.325193796266667 - // - const maxZoom = Math.pow(2, 40); - // In addition to capping zoom to avoid floating point error, we further cap - // zoom to avoid letting you zoom in so that the smallest element more than - // fills the screen, since that probably isn't useful. The final zoom cap is - // determined by the minimum zoom of either 2^40x zoom or the necessary zoom - // for the smallest frame to fill the screen three times. - const minWidth = clamp(3 * this.getMinFrameWidth(), maxWidth / maxZoom, maxWidth); - return clamp(viewportWidth, minWidth, maxWidth); - } + source: FlamechartDataSource; + + // Bottom to top + layers: StackLayer[]; + totalWeight: number; + minFrameWidth: number; + + constructor(source: FlamechartDataSource) { + this.source = source; + + // Bottom to top + this.layers = []; + this.totalWeight = 0; + this.minFrameWidth = 1; + + const stack: FlamechartFrame[] = []; + const openFrame = (node, value) => { + const parent = lastOf(stack); + const frame = { + node, + parent, + children: [], + start: value, + end: value, + }; + if (parent) { + parent.children.push(frame); + } + stack.push(frame); + }; + this.minFrameWidth = Infinity; + const closeFrame = (node, value) => { + console.assert(stack.length > 0); + const stackTop = stack.pop(); + stackTop.end = value; + if (stackTop.end - stackTop.start === 0) return; + const layerIndex = stack.length; + while (this.layers.length <= layerIndex) this.layers.push([]); + this.layers[layerIndex].push(stackTop); + this.minFrameWidth = Math.min( + this.minFrameWidth, + stackTop.end - stackTop.start + ); + }; + this.totalWeight = source.getTotalWeight(); + source.forEachCall(openFrame, closeFrame); + if (!isFinite(this.minFrameWidth)) this.minFrameWidth = 1; + } + getTotalWeight() { + return this.totalWeight; + } + getLayers(): StackLayer[] { + return this.layers; + } + getColorBucketForFrame(frame: Frame) { + return this.source.getColorBucketForFrame(frame); + } + getMinFrameWidth() { + return this.minFrameWidth; + } + formatValue(v) { + return this.source.formatValue(v); + } + getClampedViewportWidth(viewportWidth: number) { + const maxWidth = this.getTotalWeight(); + // In order to avoid floating point error, we cap the maximum zoom. In + // particular, it's important that at the maximum zoom level, the total + // trace size + a viewport width is not equal to the trace size due to + // floating point rounding. + // + // For instance, if the profile's total weight is 2^60, and the viewport + // size is 1, trying to move one viewport width right will result in no + // change because 2^60 + 1 = 2^60 in floating point arithmetic. JavaScript + // numbers are 64 bit floats, and therefore have 53 mantissa bits. You can + // see this for yourself in the console. Try: + // + // > Math.pow(2, 60) + 1 === Math.pow(2, 60) + // true + // > Math.pow(2, 53) + 1 === Math.pow(2, 53) + // true + // > Math.pow(2, 52) + 1 === Math.pow(2, 52) + // false + // + // We use 2^40 as a cap instead, since we want to be able to make small + // adjustments within a viewport width. + // + // For reference, this will still allow you to zoom until 1 nanosecond fills + // the screen in a profile with a duration of over 18 minutes. + // + // > Math.pow(2, 40) / (60 * Math.pow(10, 9)) + // 18.325193796266667 + // + const maxZoom = Math.pow(2, 40); + // In addition to capping zoom to avoid floating point error, we further cap + // zoom to avoid letting you zoom in so that the smallest element more than + // fills the screen, since that probably isn't useful. The final zoom cap is + // determined by the minimum zoom of either 2^40x zoom or the necessary zoom + // for the smallest frame to fill the screen three times. + const minWidth = clamp( + 3 * this.getMinFrameWidth(), + maxWidth / maxZoom, + maxWidth + ); + return clamp(viewportWidth, minWidth, maxWidth); + } } diff --git a/src/speedscope/lib/profile.js b/src/speedscope/lib/profile.js index e66ffbd023f20..d83a5e8fca2f9 100644 --- a/src/speedscope/lib/profile.js +++ b/src/speedscope/lib/profile.js @@ -1,514 +1,604 @@ -import {lastOf, KeyedSet} from './utils' -import {ValueFormatter, RawValueFormatter} from './value-formatters' -import {FileFormat} from './file-format-spec' -const demangleCppModule = import('./demangle-cpp') +// @flow + +import { lastOf, KeyedSet } from './utils'; +import { ValueFormatter, RawValueFormatter } from './value-formatters'; +import { FileFormat } from './file-format-spec'; +const demangleCppModule = import('./demangle-cpp'); // Force eager loading of the module -demangleCppModule.then(() => {}) +demangleCppModule.then(() => {}); export class HasWeights { - constructor() { - this.selfWeight = 0; - this.totalWeight = 0; - } - getSelfWeight() { - return this.selfWeight; - } - getTotalWeight() { - return this.totalWeight; - } - addToTotalWeight(delta) { - this.totalWeight += delta; - } - addToSelfWeight(delta) { - this.selfWeight += delta; - } - overwriteWeightWith(other) { - this.selfWeight = other.selfWeight; - this.totalWeight = other.totalWeight; - } + constructor() { + this.selfWeight = 0; + this.totalWeight = 0; + } + getSelfWeight() { + return this.selfWeight; + } + getTotalWeight() { + return this.totalWeight; + } + addToTotalWeight(delta) { + this.totalWeight += delta; + } + addToSelfWeight(delta) { + this.selfWeight += delta; + } + overwriteWeightWith(other) { + this.selfWeight = other.selfWeight; + this.totalWeight = other.totalWeight; + } } + export class Frame extends HasWeights { - constructor(info) { - super(); - this.key = info.key; - this.name = info.name; - this.file = info.file; - this.line = info.line; - this.col = info.col; - } - static getOrInsert(set, info) { - return set.getOrInsert(new Frame(info)); - } + static root: Frame; + + key: string | number; + + /** + * Name of the frame. May be a method name, e.g. "ActiveRecord##to_hash" + */ + name: string; + + /** + * File path of the code corresponding to this call stack frame. + */ + file: ?string; + + /** + * Line in the given file where this frame occurs + */ + line: ?number; + + /** + * Column in the file + */ + col: ?number; + + constructor(info) { + super(); + this.key = info.key; + this.name = info.name; + this.file = info.file; + this.line = info.line; + this.col = info.col; + } + static getOrInsert(set, info) { + return set.getOrInsert(new Frame(info)); + } } + Frame.root = new Frame({ - key: '(speedscope root)', - name: '(speedscope root)', + key: '(speedscope root)', + name: '(speedscope root)', }); + export class CallTreeNode extends HasWeights { - constructor(frame, parent) { - super(); - this.frame = frame; - this.parent = parent; - this.children = []; - // If a node is "frozen", it means it should no longer be mutated. - this.frozen = false; - } - isRoot() { - return this.frame === Frame.root; - } - isFrozen() { - return this.frozen; - } - freeze() { - this.frozen = true; - } + frame: Frame; + + children: CallTreeNode[]; + frozen: boolean; + + constructor(frame: Frame, parent) { + super(); + this.frame = frame; + this.parent = parent; + this.children = []; + // If a node is "frozen", it means it should no longer be mutated. + this.frozen = false; + } + isRoot() { + return this.frame === Frame.root; + } + isFrozen() { + return this.frozen; + } + freeze() { + this.frozen = true; + } +} + +export interface ProfileGroup { + name: string; + indexToView: number; + profiles: Profile[]; } + export class Profile { - constructor(totalWeight = 0) { - this.name = ''; - this.frames = new KeyedSet(); - this.appendOrderCalltreeRoot = new CallTreeNode(Frame.root, null); - this.groupedCalltreeRoot = new CallTreeNode(Frame.root, null); - // List of references to CallTreeNodes at the top of the - // stack at the time of the sample. - this.samples = []; - this.weights = []; - this.valueFormatter = new RawValueFormatter(); - this.totalNonIdleWeight = null; - this.totalWeight = totalWeight; - } - getAppendOrderCalltreeRoot() { - return this.appendOrderCalltreeRoot; - } - getGroupedCalltreeRoot() { - return this.groupedCalltreeRoot; - } - formatValue(v) { - return this.valueFormatter.format(v); - } - setValueFormatter(f) { - this.valueFormatter = f; - } - getWeightUnit() { - return this.valueFormatter.unit; - } - getName() { - return this.name; - } - setName(name) { - this.name = name; - } - getTotalWeight() { - return this.totalWeight; - } - getTotalNonIdleWeight() { - if (this.totalNonIdleWeight === null) { - this.totalNonIdleWeight = this.groupedCalltreeRoot.children.reduce((n, c) => n + c.getTotalWeight(), 0); - } - return this.totalNonIdleWeight; - } - forEachCallGrouped(openFrame, closeFrame) { - function visit(node, start) { - if (node.frame !== Frame.root) { - openFrame(node, start); - } - let childTime = 0; - const children = [...node.children]; - children.sort((a, b) => (a.getTotalWeight() > b.getTotalWeight() ? -1 : 1)); - children.forEach(function (child) { - visit(child, start + childTime); - childTime += child.getTotalWeight(); - }); - if (node.frame !== Frame.root) { - closeFrame(node, start + node.getTotalWeight()); - } - } - visit(this.groupedCalltreeRoot, 0); - } - forEachCall(openFrame, closeFrame) { - let prevStack = []; - let value = 0; - let sampleIndex = 0; - for (let stackTop of this.samples) { - // Find lowest common ancestor of the current stack and the previous one - let lca = null; - // This is O(n^2), but n should be relatively small here (stack height), - // so hopefully this isn't much of a problem - for (lca = stackTop; lca && lca.frame != Frame.root && prevStack.indexOf(lca) === -1; lca = lca.parent) { } - // Close frames that are no longer open - while (prevStack.length > 0 && lastOf(prevStack) != lca) { - const node = prevStack.pop(); - closeFrame(node, value); - } - // Open frames that are now becoming open - const toOpen = []; - for (let node = stackTop; node && node.frame != Frame.root && node != lca; node = node.parent) { - toOpen.push(node); - } - toOpen.reverse(); - for (let node of toOpen) { - openFrame(node, value); - } - prevStack = prevStack.concat(toOpen); - value += this.weights[sampleIndex++]; - } - // Close frames that are open at the end of the trace - for (let i = prevStack.length - 1; i >= 0; i--) { - closeFrame(prevStack[i], value); - } - } - forEachFrame(fn) { - this.frames.forEach(fn); - } - forEachSample(fn) { - for (let i = 0; i < this.samples.length; i++) { - fn(this.samples[i], this.weights[i]); - } - } - getProfileWithRecursionFlattened() { - const builder = new CallTreeProfileBuilder(); - const stack = []; - const framesInStack = new Set(); - function openFrame(node, value) { - if (framesInStack.has(node.frame)) { - stack.push(null); - } - else { - framesInStack.add(node.frame); - stack.push(node); - builder.enterFrame(node.frame, value); - } - } - function closeFrame(node, value) { - const stackTop = stack.pop(); - if (stackTop) { - framesInStack.delete(stackTop.frame); - builder.leaveFrame(stackTop.frame, value); - } - } - this.forEachCall(openFrame, closeFrame); - const flattenedProfile = builder.build(); - flattenedProfile.name = this.name; - flattenedProfile.valueFormatter = this.valueFormatter; - // When constructing a profile with recursion flattened, - // counter-intuitive things can happen to "self time" measurements - // for functions. - // For example, given the following list of stacks w/ weights: - // - // a 1 - // a;b;a 1 - // a;b;a;b;a 1 - // a;b;a 1 - // - // The resulting profile with recursion flattened out will look like this: - // - // a 1 - // a;b 3 - // - // Which is useful to view, but it's counter-intuitive to move self-time - // for frames around, since analyzing the self-time of functions is an important - // thing to be able to do accurately, and we don't want this to change when recursion - // is flattened. To work around that, we'll just copy the weights directly from the - // un-flattened profile. - this.forEachFrame(f => { - flattenedProfile.frames.getOrInsert(f).overwriteWeightWith(f); - }); - return flattenedProfile; - } - getInvertedProfileForCallersOf(focalFrameInfo) { - const focalFrame = Frame.getOrInsert(this.frames, focalFrameInfo); - const builder = new StackListProfileBuilder(); - // TODO(jlfwong): Could construct this at profile - // construction time rather than on demand. - const nodes = []; - function visit(node) { - if (node.frame === focalFrame) { - nodes.push(node); - } - else { - for (let child of node.children) { - visit(child); - } - } - } - visit(this.appendOrderCalltreeRoot); - for (let node of nodes) { - const stack = []; - for (let n = node; n != null && n.frame !== Frame.root; n = n.parent) { - stack.push(n.frame); - } - builder.appendSampleWithWeight(stack, node.getTotalWeight()); + name: string; + totalWeight: number; + frames: KeyedSet; + + appendOrderCalltreeRoot: CallTreeNode; + groupedCalltreeRoot: CallTreeNode; + + // List of references to CallTreeNodes at the top of the + // stack at the time of the sample. + samples: CallTreeNode[]; + weights: number[]; + + valueFormatter: ValueFormatter; + + totalNonIdleWeight: number | null; + + constructor(totalWeight: number = 0) { + this.name = ''; + this.frames = new KeyedSet(); + this.appendOrderCalltreeRoot = new CallTreeNode(Frame.root, null); + this.groupedCalltreeRoot = new CallTreeNode(Frame.root, null); + // List of references to CallTreeNodes at the top of the + // stack at the time of the sample. + this.samples = []; + this.weights = []; + this.valueFormatter = new RawValueFormatter(); + this.totalNonIdleWeight = null; + this.totalWeight = totalWeight; + } + getAppendOrderCalltreeRoot() { + return this.appendOrderCalltreeRoot; + } + getGroupedCalltreeRoot() { + return this.groupedCalltreeRoot; + } + formatValue(v: number) { + return this.valueFormatter.format(v); + } + setValueFormatter(f: ValueFormatter) { + this.valueFormatter = f; + } + getWeightUnit() { + return this.valueFormatter.unit; + } + getName() { + return this.name; + } + setName(name: string) { + this.name = name; + } + getTotalWeight() { + return this.totalWeight; + } + getTotalNonIdleWeight() { + if (this.totalNonIdleWeight === null) { + this.totalNonIdleWeight = this.groupedCalltreeRoot.children.reduce( + (n, c) => n + c.getTotalWeight(), + 0 + ); + } + return this.totalNonIdleWeight; + } + forEachCallGrouped( + openFrame: (node: CallTreeNode, value: number) => void, + closeFrame: (node: CallTreeNode, value: number) => void + ) { + function visit(node, start) { + if (node.frame !== Frame.root) { + openFrame(node, start); + } + let childTime = 0; + const children = [...node.children]; + children.sort((a, b) => + a.getTotalWeight() > b.getTotalWeight() ? -1 : 1 + ); + children.forEach(function(child) { + visit(child, start + childTime); + childTime += child.getTotalWeight(); + }); + if (node.frame !== Frame.root) { + closeFrame(node, start + node.getTotalWeight()); + } + } + visit(this.groupedCalltreeRoot, 0); + } + forEachCall( + openFrame: (node: CallTreeNode, value: number) => void, + closeFrame: (node: CallTreeNode, value: number) => void + ) { + let prevStack = []; + let value = 0; + let sampleIndex = 0; + for (let stackTop of this.samples) { + // Find lowest common ancestor of the current stack and the previous one + let lca = null; + // This is O(n^2), but n should be relatively small here (stack height), + // so hopefully this isn't much of a problem + for ( + lca = stackTop; + lca && lca.frame != Frame.root && prevStack.indexOf(lca) === -1; + lca = lca.parent + ) {} + // Close frames that are no longer open + while (prevStack.length > 0 && lastOf(prevStack) != lca) { + const node = prevStack.pop(); + closeFrame(node, value); + } + // Open frames that are now becoming open + const toOpen = []; + for ( + let node = stackTop; + node && node.frame != Frame.root && node != lca; + node = node.parent + ) { + toOpen.push(node); + } + toOpen.reverse(); + for (let node of toOpen) { + openFrame(node, value); + } + prevStack = prevStack.concat(toOpen); + value += this.weights[sampleIndex++]; + } + // Close frames that are open at the end of the trace + for (let i = prevStack.length - 1; i >= 0; i--) { + closeFrame(prevStack[i], value); + } + } + forEachFrame(fn: (frame: Frame) => void) { + this.frames.forEach(fn); + } + forEachSample(fn: (sample: CallTreeNode, weight: number) => void) { + for (let i = 0; i < this.samples.length; i++) { + fn(this.samples[i], this.weights[i]); + } + } + getProfileWithRecursionFlattened() { + const builder = new CallTreeProfileBuilder(); + const stack = []; + const framesInStack = new Set(); + function openFrame(node, value) { + if (framesInStack.has(node.frame)) { + stack.push(null); + } else { + framesInStack.add(node.frame); + stack.push(node); + builder.enterFrame(node.frame, value); + } + } + function closeFrame(node, value) { + const stackTop = stack.pop(); + if (stackTop) { + framesInStack.delete(stackTop.frame); + builder.leaveFrame(stackTop.frame, value); + } + } + this.forEachCall(openFrame, closeFrame); + const flattenedProfile = builder.build(); + flattenedProfile.name = this.name; + flattenedProfile.valueFormatter = this.valueFormatter; + // When constructing a profile with recursion flattened, + // counter-intuitive things can happen to "self time" measurements + // for functions. + // For example, given the following list of stacks w/ weights: + // + // a 1 + // a;b;a 1 + // a;b;a;b;a 1 + // a;b;a 1 + // + // The resulting profile with recursion flattened out will look like this: + // + // a 1 + // a;b 3 + // + // Which is useful to view, but it's counter-intuitive to move self-time + // for frames around, since analyzing the self-time of functions is an important + // thing to be able to do accurately, and we don't want this to change when recursion + // is flattened. To work around that, we'll just copy the weights directly from the + // un-flattened profile. + this.forEachFrame(f => { + flattenedProfile.frames.getOrInsert(f).overwriteWeightWith(f); + }); + return flattenedProfile; + } + getInvertedProfileForCallersOf(focalFrameInfo) { + const focalFrame = Frame.getOrInsert(this.frames, focalFrameInfo); + const builder = new StackListProfileBuilder(); + // TODO(jlfwong): Could construct this at profile + // construction time rather than on demand. + const nodes = []; + function visit(node) { + if (node.frame === focalFrame) { + nodes.push(node); + } else { + for (let child of node.children) { + visit(child); } - const ret = builder.build(); - ret.name = this.name; - ret.valueFormatter = this.valueFormatter; - return ret; - } - getProfileForCalleesOf(focalFrameInfo) { - const focalFrame = Frame.getOrInsert(this.frames, focalFrameInfo); - const builder = new StackListProfileBuilder(); - function recordSubtree(focalFrameNode) { - const stack = []; - function visit(node) { - stack.push(node.frame); - builder.appendSampleWithWeight(stack, node.getSelfWeight()); - for (let child of node.children) { - visit(child); - } - stack.pop(); - } - visit(focalFrameNode); + } + } + visit(this.appendOrderCalltreeRoot); + for (let node of nodes) { + const stack = []; + for (let n = node; n != null && n.frame !== Frame.root; n = n.parent) { + stack.push(n.frame); + } + builder.appendSampleWithWeight(stack, node.getTotalWeight()); + } + const ret = builder.build(); + ret.name = this.name; + ret.valueFormatter = this.valueFormatter; + return ret; + } + getProfileForCalleesOf(focalFrameInfo) { + const focalFrame = Frame.getOrInsert(this.frames, focalFrameInfo); + const builder = new StackListProfileBuilder(); + function recordSubtree(focalFrameNode) { + const stack = []; + function visit(node) { + stack.push(node.frame); + builder.appendSampleWithWeight(stack, node.getSelfWeight()); + for (let child of node.children) { + visit(child); } - function findCalls(node) { - if (node.frame === focalFrame) { - recordSubtree(node); - } - else { - for (let child of node.children) { - findCalls(child); - } - } + stack.pop(); + } + visit(focalFrameNode); + } + function findCalls(node) { + if (node.frame === focalFrame) { + recordSubtree(node); + } else { + for (let child of node.children) { + findCalls(child); } - findCalls(this.appendOrderCalltreeRoot); - const ret = builder.build(); - ret.name = this.name; - ret.valueFormatter = this.valueFormatter; - return ret; - } - // Demangle symbols for readability - async demangle() { - let demangleCpp = null; - for (let frame of this.frames) { - // This function converts a mangled C++ name such as "__ZNK7Support6ColorFeqERKS0_" - // into a human-readable symbol (in this case "Support::ColorF::==(Support::ColorF&)") - if (frame.name.startsWith('__Z')) { - if (!demangleCpp) { - demangleCpp = (await demangleCppModule).demangleCpp; - } - frame.name = demangleCpp(frame.name); - } + } + } + findCalls(this.appendOrderCalltreeRoot); + const ret = builder.build(); + ret.name = this.name; + ret.valueFormatter = this.valueFormatter; + return ret; + } + // Demangle symbols for readability + async demangle() { + let demangleCpp = null; + for (let frame of this.frames) { + // This function converts a mangled C++ name such as "__ZNK7Support6ColorFeqERKS0_" + // into a human-readable symbol (in this case "Support::ColorF::==(Support::ColorF&)") + if (frame.name.startsWith('__Z')) { + if (!demangleCpp) { + demangleCpp = (await demangleCppModule).demangleCpp; } + frame.name = demangleCpp(frame.name); + } } - remapNames(callback) { - for (let frame of this.frames) { - frame.name = callback(frame.name); - } + } + remapNames(callback) { + for (let frame of this.frames) { + frame.name = callback(frame.name); } + } } export class StackListProfileBuilder extends Profile { - constructor() { - super(...arguments); - this.pendingSample = null; - } - _appendSample(stack, weight, useAppendOrder) { - if (isNaN(weight)) - throw new Error('invalid weight'); - let node = useAppendOrder ? this.appendOrderCalltreeRoot : this.groupedCalltreeRoot; - let framesInStack = new Set(); - for (let frameInfo of stack) { - const frame = Frame.getOrInsert(this.frames, frameInfo); - const last = useAppendOrder - ? lastOf(node.children) - : node.children.find(c => c.frame === frame); - if (last && !last.isFrozen() && last.frame == frame) { - node = last; - } - else { - const parent = node; - node = new CallTreeNode(frame, node); - parent.children.push(node); - } - node.addToTotalWeight(weight); - // It's possible for the same frame to occur multiple - // times in the same call stack due to either direct - // or indirect recursion. We want to avoid counting that - // frame multiple times for a single sample, we so just - // track all of the unique frames that participated in - // this call stack, then add to their weight at the end. - framesInStack.add(node.frame); - } - node.addToSelfWeight(weight); - if (useAppendOrder) { - for (let child of node.children) { - child.freeze(); - } - } - if (useAppendOrder) { - node.frame.addToSelfWeight(weight); - for (let frame of framesInStack) { - frame.addToTotalWeight(weight); - } - if (node === lastOf(this.samples)) { - this.weights[this.weights.length - 1] += weight; - } - else { - this.samples.push(node); - this.weights.push(weight); - } - } - } - appendSampleWithWeight(stack, weight) { - if (weight === 0) { - // Samples with zero weight have no effect, so let's ignore them - return; - } - if (weight < 0) { - throw new Error('Samples must have positive weights'); - } - this._appendSample(stack, weight, true); - this._appendSample(stack, weight, false); - } - appendSampleWithTimestamp(stack, timestamp) { - if (this.pendingSample) { - if (timestamp < this.pendingSample.centralTimestamp) { - throw new Error('Timestamps received out of order'); - } - const endTimestamp = (timestamp + this.pendingSample.centralTimestamp) / 2; - this.appendSampleWithWeight(this.pendingSample.stack, endTimestamp - this.pendingSample.startTimestamp); - this.pendingSample = { stack, startTimestamp: endTimestamp, centralTimestamp: timestamp }; - } - else { - this.pendingSample = { stack, startTimestamp: timestamp, centralTimestamp: timestamp }; - } - } - build() { - if (this.pendingSample) { - if (this.samples.length > 0) { - this.appendSampleWithWeight(this.pendingSample.stack, this.pendingSample.centralTimestamp - this.pendingSample.startTimestamp); - } - else { - // There is only a single sample. In this case, units will be meaningless, - // so we'll append with a weight of 1 and also clear any value formatter - this.appendSampleWithWeight(this.pendingSample.stack, 1); - this.setValueFormatter(new RawValueFormatter()); - } - } - this.totalWeight = Math.max(this.totalWeight, this.weights.reduce((a, b) => a + b, 0)); - return this; - } + constructor() { + super(...arguments); + this.pendingSample = null; + } + _appendSample(stack, weight, useAppendOrder) { + if (isNaN(weight)) throw new Error('invalid weight'); + let node = useAppendOrder + ? this.appendOrderCalltreeRoot + : this.groupedCalltreeRoot; + let framesInStack = new Set(); + for (let frameInfo of stack) { + const frame = Frame.getOrInsert(this.frames, frameInfo); + const last = useAppendOrder + ? lastOf(node.children) + : node.children.find(c => c.frame === frame); + if (last && !last.isFrozen() && last.frame == frame) { + node = last; + } else { + const parent = node; + node = new CallTreeNode(frame, node); + parent.children.push(node); + } + node.addToTotalWeight(weight); + // It's possible for the same frame to occur multiple + // times in the same call stack due to either direct + // or indirect recursion. We want to avoid counting that + // frame multiple times for a single sample, we so just + // track all of the unique frames that participated in + // this call stack, then add to their weight at the end. + framesInStack.add(node.frame); + } + node.addToSelfWeight(weight); + if (useAppendOrder) { + for (let child of node.children) { + child.freeze(); + } + } + if (useAppendOrder) { + node.frame.addToSelfWeight(weight); + for (let frame of framesInStack) { + frame.addToTotalWeight(weight); + } + if (node === lastOf(this.samples)) { + this.weights[this.weights.length - 1] += weight; + } else { + this.samples.push(node); + this.weights.push(weight); + } + } + } + appendSampleWithWeight(stack, weight) { + if (weight === 0) { + // Samples with zero weight have no effect, so let's ignore them + return; + } + if (weight < 0) { + throw new Error('Samples must have positive weights'); + } + this._appendSample(stack, weight, true); + this._appendSample(stack, weight, false); + } + appendSampleWithTimestamp(stack, timestamp) { + if (this.pendingSample) { + if (timestamp < this.pendingSample.centralTimestamp) { + throw new Error('Timestamps received out of order'); + } + const endTimestamp = + (timestamp + this.pendingSample.centralTimestamp) / 2; + this.appendSampleWithWeight( + this.pendingSample.stack, + endTimestamp - this.pendingSample.startTimestamp + ); + this.pendingSample = { + stack, + startTimestamp: endTimestamp, + centralTimestamp: timestamp, + }; + } else { + this.pendingSample = { + stack, + startTimestamp: timestamp, + centralTimestamp: timestamp, + }; + } + } + build() { + if (this.pendingSample) { + if (this.samples.length > 0) { + this.appendSampleWithWeight( + this.pendingSample.stack, + this.pendingSample.centralTimestamp - + this.pendingSample.startTimestamp + ); + } else { + // There is only a single sample. In this case, units will be meaningless, + // so we'll append with a weight of 1 and also clear any value formatter + this.appendSampleWithWeight(this.pendingSample.stack, 1); + this.setValueFormatter(new RawValueFormatter()); + } + } + this.totalWeight = Math.max( + this.totalWeight, + this.weights.reduce((a, b) => a + b, 0) + ); + return this; + } } // As an alternative API for importing profiles more efficiently, provide a // way to open & close frames directly without needing to construct tons of // arrays as intermediaries. export class CallTreeProfileBuilder extends Profile { - constructor() { - super(...arguments); - this.appendOrderStack = [this.appendOrderCalltreeRoot]; - this.groupedOrderStack = [this.groupedCalltreeRoot]; - this.framesInStack = new Map(); - this.stack = []; - this.lastValue = 0; - } - addWeightsToFrames(value) { + constructor() { + super(...arguments); + this.appendOrderStack = [this.appendOrderCalltreeRoot]; + this.groupedOrderStack = [this.groupedCalltreeRoot]; + this.framesInStack = new Map(); + this.stack = []; + this.lastValue = 0; + } + addWeightsToFrames(value) { + const delta = value - this.lastValue; + for (let frame of this.framesInStack.keys()) { + frame.addToTotalWeight(delta); + } + const stackTop = lastOf(this.stack); + if (stackTop) { + stackTop.addToSelfWeight(delta); + } + } + addWeightsToNodes(value, stack) { + const delta = value - this.lastValue; + for (let node of stack) { + node.addToTotalWeight(delta); + } + const stackTop = lastOf(stack); + if (stackTop) { + stackTop.addToSelfWeight(delta); + } + } + _enterFrame(frame, value, useAppendOrder) { + let stack = useAppendOrder ? this.appendOrderStack : this.groupedOrderStack; + this.addWeightsToNodes(value, stack); + let prevTop = lastOf(stack); + if (prevTop) { + if (useAppendOrder) { const delta = value - this.lastValue; - for (let frame of this.framesInStack.keys()) { - frame.addToTotalWeight(delta); - } - const stackTop = lastOf(this.stack); - if (stackTop) { - stackTop.addToSelfWeight(delta); - } - } - addWeightsToNodes(value, stack) { - const delta = value - this.lastValue; - for (let node of stack) { - node.addToTotalWeight(delta); - } - const stackTop = lastOf(stack); - if (stackTop) { - stackTop.addToSelfWeight(delta); - } - } - _enterFrame(frame, value, useAppendOrder) { - let stack = useAppendOrder ? this.appendOrderStack : this.groupedOrderStack; - this.addWeightsToNodes(value, stack); - let prevTop = lastOf(stack); - if (prevTop) { - if (useAppendOrder) { - const delta = value - this.lastValue; - if (delta > 0) { - this.samples.push(prevTop); - this.weights.push(value - this.lastValue); - } - else if (delta < 0) { - throw new Error(`Samples must be provided in increasing order of cumulative value. Last sample was ${this.lastValue}, this sample was ${value}`); - } - } - const last = useAppendOrder - ? lastOf(prevTop.children) - : prevTop.children.find(c => c.frame === frame); - let node; - if (last && !last.isFrozen() && last.frame == frame) { - node = last; - } - else { - node = new CallTreeNode(frame, prevTop); - prevTop.children.push(node); - } - stack.push(node); - } - } - enterFrame(frameInfo, value) { - const frame = Frame.getOrInsert(this.frames, frameInfo); - this.addWeightsToFrames(value); - this._enterFrame(frame, value, true); - this._enterFrame(frame, value, false); - this.stack.push(frame); - const frameCount = this.framesInStack.get(frame) || 0; - this.framesInStack.set(frame, frameCount + 1); - this.lastValue = value; - } - _leaveFrame(frame, value, useAppendOrder) { - let stack = useAppendOrder ? this.appendOrderStack : this.groupedOrderStack; - this.addWeightsToNodes(value, stack); - if (useAppendOrder) { - const leavingStackTop = this.appendOrderStack.pop(); - if (leavingStackTop == null) { - throw new Error(`Trying to leave ${frame.key} when stack is empty`); - } - if (this.lastValue == null) { - throw new Error(`Trying to leave a ${frame.key} before any have been entered`); - } - leavingStackTop.freeze(); - const delta = value - this.lastValue; - if (delta > 0) { - this.samples.push(leavingStackTop); - this.weights.push(value - this.lastValue); - } - else if (delta < 0) { - throw new Error(`Samples must be provided in increasing order of cumulative value. Last sample was ${this - .lastValue}, this sample was ${value}`); - } - } - else { - this.groupedOrderStack.pop(); + if (delta > 0) { + this.samples.push(prevTop); + this.weights.push(value - this.lastValue); + } else if (delta < 0) { + throw new Error( + `Samples must be provided in increasing order of cumulative value. Last sample was ${this.lastValue}, this sample was ${value}` + ); } - } - leaveFrame(frameInfo, value) { - const frame = Frame.getOrInsert(this.frames, frameInfo); - this.addWeightsToFrames(value); - this._leaveFrame(frame, value, true); - this._leaveFrame(frame, value, false); - this.stack.pop(); - const frameCount = this.framesInStack.get(frame); - if (frameCount == null) - return; - if (frameCount === 1) { - this.framesInStack.delete(frame); - } - else { - this.framesInStack.set(frame, frameCount - 1); - } - this.lastValue = value; - this.totalWeight = Math.max(this.totalWeight, this.lastValue); - } - build() { - // Each stack is expected to contain a single node which we initialize to be - // the root node. - if (this.appendOrderStack.length > 1 || this.groupedOrderStack.length > 1) { - throw new Error('Tried to complete profile construction with a non-empty stack'); - } - return this; - } + } + const last = useAppendOrder + ? lastOf(prevTop.children) + : prevTop.children.find(c => c.frame === frame); + let node; + if (last && !last.isFrozen() && last.frame == frame) { + node = last; + } else { + node = new CallTreeNode(frame, prevTop); + prevTop.children.push(node); + } + stack.push(node); + } + } + enterFrame(frameInfo, value) { + const frame = Frame.getOrInsert(this.frames, frameInfo); + this.addWeightsToFrames(value); + this._enterFrame(frame, value, true); + this._enterFrame(frame, value, false); + this.stack.push(frame); + const frameCount = this.framesInStack.get(frame) || 0; + this.framesInStack.set(frame, frameCount + 1); + this.lastValue = value; + } + _leaveFrame(frame, value, useAppendOrder) { + let stack = useAppendOrder ? this.appendOrderStack : this.groupedOrderStack; + this.addWeightsToNodes(value, stack); + if (useAppendOrder) { + const leavingStackTop = this.appendOrderStack.pop(); + if (leavingStackTop == null) { + throw new Error(`Trying to leave ${frame.key} when stack is empty`); + } + if (this.lastValue == null) { + throw new Error( + `Trying to leave a ${frame.key} before any have been entered` + ); + } + leavingStackTop.freeze(); + const delta = value - this.lastValue; + if (delta > 0) { + this.samples.push(leavingStackTop); + this.weights.push(value - this.lastValue); + } else if (delta < 0) { + throw new Error( + `Samples must be provided in increasing order of cumulative value. Last sample was ${this.lastValue}, this sample was ${value}` + ); + } + } else { + this.groupedOrderStack.pop(); + } + } + leaveFrame(frameInfo, value) { + const frame = Frame.getOrInsert(this.frames, frameInfo); + this.addWeightsToFrames(value); + this._leaveFrame(frame, value, true); + this._leaveFrame(frame, value, false); + this.stack.pop(); + const frameCount = this.framesInStack.get(frame); + if (frameCount == null) return; + if (frameCount === 1) { + this.framesInStack.delete(frame); + } else { + this.framesInStack.set(frame, frameCount - 1); + } + this.lastValue = value; + this.totalWeight = Math.max(this.totalWeight, this.lastValue); + } + build() { + // Each stack is expected to contain a single node which we initialize to be + // the root node. + if (this.appendOrderStack.length > 1 || this.groupedOrderStack.length > 1) { + throw new Error( + 'Tried to complete profile construction with a non-empty stack' + ); + } + return this; + } } diff --git a/src/types.js b/src/types.js index 442b590e083e6..92a9c9b013acb 100644 --- a/src/types.js +++ b/src/types.js @@ -1,5 +1,7 @@ // @flow +import { Flamechart } from './speedscope/lib/flamechart'; + export type Milliseconds = number; export type ReactPriority = 'unscheduled' | 'high' | 'normal' | 'low'; @@ -57,4 +59,4 @@ export type ReactHoverContextInfo = {| zeroAt: Milliseconds, |}; -export type FlamechartData = any; +export type FlamechartData = Flamechart; diff --git a/src/useDebounce.js b/src/useDebounce.js index cc706172e0646..93947aaf08a2f 100644 --- a/src/useDebounce.js +++ b/src/useDebounce.js @@ -1,28 +1,34 @@ -// Below copied from https://usehooks.com/ -export default function useDebounce(value, delay) { - // State and setters for debounced value - const [debouncedValue, setDebouncedValue] = useState(value); +// @flow - // Show the value in DevTools - useDebugValue(debouncedValue); +// TODO: Remove if unused - useEffect( - () => { - // Update debounced value after delay - const handler = setTimeout(() => { - setDebouncedValue(value); - }, delay); +// import { useDebugValue, useEffect, useState } from 'react'; - // Cancel the timeout if value changes (also on delay change or unmount) - // This is how we prevent debounced value from updating if value is changed ... - // .. within the delay period. Timeout gets cleared and restarted. - return () => { - clearTimeout(handler); - }; - }, - [value, delay] // Only re-call effect if value or delay changes - ); +// // Below copied from https://usehooks.com/ +// export default function useDebounce(value: T, delay: number): T { +// // State and setters for debounced value +// const [debouncedValue, setDebouncedValue] = useState(value); - return debouncedValue; -} -// Above copied from https://usehooks.com/ +// // Show the value in DevTools +// useDebugValue(debouncedValue); + +// useEffect( +// () => { +// // Update debounced value after delay +// const handler = setTimeout(() => { +// setDebouncedValue(value); +// }, delay); + +// // Cancel the timeout if value changes (also on delay change or unmount) +// // This is how we prevent debounced value from updating if value is changed ... +// // .. within the delay period. Timeout gets cleared and restarted. +// return () => { +// clearTimeout(handler); +// }; +// }, +// [value, delay] // Only re-call effect if value or delay changes +// ); + +// return debouncedValue; +// } +// // Above copied from https://usehooks.com/ diff --git a/src/useInteractiveEvents.js b/src/useInteractiveEvents.js index cb52eec8e7043..65680565b539e 100644 --- a/src/useInteractiveEvents.js +++ b/src/useInteractiveEvents.js @@ -1,3 +1,5 @@ +// @flow + import { useEffect, useRef, useState } from 'react'; import { durationToWidth, timestampToPosition } from './usePanAndZoom'; import { EVENT_SIZE } from './constants'; diff --git a/src/usePanAndZoom.js b/src/usePanAndZoom.js index 76301f4c595fd..01c4ce89402eb 100644 --- a/src/usePanAndZoom.js +++ b/src/usePanAndZoom.js @@ -1,3 +1,5 @@ +// @flow + import { useEffect, useReducer } from 'react'; import { getCanvasMousePos } from './canvasUtils'; import { @@ -9,7 +11,24 @@ import { ZOOM_WHEEL_DELTA_THRESHOLD, } from './constants'; -const initialState = { +type State = {| + canvasHeight: number, + canvasWidth: number, + canvasMouseX: number, + canvasMouseY: number, + fixedColumnWidth: number, + fixedHeaderHeight: number, + isDragging: boolean, + minZoomLevel: number, + offsetX: number, + offsetY: number, + unscaledContentHeight: number, + unscaledContentWidth: number, + zoomLevel: number, + zoomTo: null | ((startTime: number, endTime: number) => void), +|}; + +const initialState: State = { canvasHeight: 0, canvasWidth: 0, canvasMouseX: 0, @@ -27,23 +46,23 @@ const initialState = { }; // TODO Account for fixed label width -export function positionToTimestamp(position, state) { +export function positionToTimestamp(position: number, state: State) { return (position - state.fixedColumnWidth + state.offsetX) / state.zoomLevel; } // TODO Account for fixed label width -export function timestampToPosition(timestamp, state) { +export function timestampToPosition(timestamp: number, state: State) { return timestamp * state.zoomLevel + state.fixedColumnWidth - state.offsetX; } -export function durationToWidth(duration, state) { +export function durationToWidth(duration: number, state: State) { return Math.max( duration * state.zoomLevel - BAR_HORIZONTAL_SPACING, MIN_BAR_WIDTH ); } -function getMaxOffsetX(state) { +function getMaxOffsetX(state: State) { return ( state.unscaledContentWidth * state.zoomLevel - state.canvasWidth + @@ -51,17 +70,58 @@ function getMaxOffsetX(state) { ); } -function getMaxOffsetY(state) { +function getMaxOffsetY(state: State) { return ( state.unscaledContentHeight - state.canvasHeight + state.fixedHeaderHeight ); } -function reducer(state, action) { - const { payload, type } = action; - switch (type) { - case 'initialize': - return { +type InitializeAction = {| + type: 'initialize', + payload: $Shape, +|}; +type MouseDownAction = {| + type: 'mouse-down', +|}; +type MouseMoveAction = {| + type: 'mouse-move', + payload: {| + canvas: HTMLCanvasElement, + event: MouseEvent, + |}, +|}; +type MouseUpAction = {| + type: 'mouse-up', +|}; +type WheelAction = {| + type: 'wheel', + payload: {| + canvas: HTMLCanvasElement, + event: WheelEvent, + |}, +|}; +type ZoomToAction = {| + type: 'zoom-to', + payload: {| + startTime: number, + stopTime: number, + |}, +|}; + +function reducer( + state: State, + action: + | InitializeAction + | MouseDownAction + | MouseMoveAction + | MouseUpAction + | WheelAction + | ZoomToAction +): State { + switch (action.type) { + case 'initialize': { + const { payload } = action; + return ({ ...state, canvasHeight: payload.canvasHeight, canvasWidth: payload.canvasWidth, @@ -73,13 +133,16 @@ function reducer(state, action) { zoomLevel: payload.zoomLevel, offsetX: clamp(0, getMaxOffsetX(state), state.offsetX), offsetY: clamp(0, getMaxOffsetY(state), state.offsetY), - }; - case 'mouse-down': + }: State); + } + case 'mouse-down': { return { ...state, isDragging: true, }; - case 'mouse-move': + } + case 'mouse-move': { + const { payload } = action; const { canvasMouseX, canvasMouseY } = getCanvasMousePos( payload.canvas, payload.event @@ -108,12 +171,15 @@ function reducer(state, action) { canvasMouseY, }; } - case 'mouse-up': + } + case 'mouse-up': { return { ...state, isDragging: false, }; - case 'wheel': + } + case 'wheel': { + const { payload } = action; const { canvas, event } = payload; const { deltaX, deltaY } = event; const { @@ -180,7 +246,9 @@ function reducer(state, action) { } } break; - case 'zoom-to': + } + case 'zoom-to': { + const { payload } = action; const { startTime, stopTime } = payload; const { canvasWidth, fixedColumnWidth } = state; @@ -192,21 +260,31 @@ function reducer(state, action) { offsetX: newZoomLevel * startTime, zoomLevel: newZoomLevel, }; - break; + } default: - throw Error(`Unexpected type "${type}"`); + throw Error(`Unexpected type "${action.type}"`); } return state; } -function clamp(min, max, value) { +function clamp(min: number, max: number, value: number): number { if (Number.isNaN(min) || Number.isNaN(max) || Number.isNaN(value)) { debugger; } return Math.max(min, Math.min(max, value)); } +type Props = {| + canvasRef: {| current: ?HTMLCanvasElement |}, + canvasHeight: number, + canvasWidth: number, + fixedColumnWidth: number, + fixedHeaderHeight: number, + unscaledContentWidth: number, + unscaledContentHeight: number, +|}; + // Inspired by https://github.com/jsdf/flamechart export default function usePanAndZoom({ canvasRef, @@ -216,10 +294,10 @@ export default function usePanAndZoom({ fixedHeaderHeight, unscaledContentWidth, unscaledContentHeight, -}) { +}: Props) { const [state, dispatch] = useReducer(reducer, { ...initialState, - zoomTo: (startTime, stopTime) => + zoomTo: (startTime: number, stopTime: number) => dispatch({ type: 'zoom-to', payload: { @@ -264,25 +342,30 @@ export default function usePanAndZoom({ useEffect(() => { const canvas = canvasRef.current; - const onCanvasMouseDown = event => { + if (!(canvas instanceof HTMLCanvasElement)) { + console.error('canvas is not a HTMLCanvasElement!', canvas); + return; + } + + const onCanvasMouseDown: MouseEventHandler = event => { dispatch({ type: 'mouse-down' }); }; - const onCanvasMouseMove = event => { + const onCanvasMouseMove: MouseEventHandler = event => { dispatch({ type: 'mouse-move', payload: { - canvas: canvasRef.current, + canvas, event, }, }); }; - const onDocumentMouseUp = event => { + const onDocumentMouseUp: MouseEventHandler = event => { dispatch({ type: 'mouse-up' }); }; - const onCanvasWheel = event => { + const onCanvasWheel: WheelEventHandler = event => { event.preventDefault(); event.stopPropagation(); @@ -299,20 +382,16 @@ export default function usePanAndZoom({ document.addEventListener('mouseup', onDocumentMouseUp); - if (canvas instanceof HTMLCanvasElement) { - canvas.addEventListener('wheel', onCanvasWheel); - canvas.addEventListener('mousedown', onCanvasMouseDown); - canvas.addEventListener('mousemove', onCanvasMouseMove); - } + canvas.addEventListener('wheel', onCanvasWheel); + canvas.addEventListener('mousedown', onCanvasMouseDown); + canvas.addEventListener('mousemove', onCanvasMouseMove); return () => { document.removeEventListener('mouseup', onDocumentMouseUp); - if (canvas instanceof HTMLCanvasElement) { - canvas.removeEventListener('wheel', onCanvasWheel); - canvas.removeEventListener('mousedown', onCanvasMouseDown); - canvas.removeEventListener('mousemove', onCanvasMouseMove); - } + canvas.removeEventListener('wheel', onCanvasWheel); + canvas.removeEventListener('mousedown', onCanvasMouseDown); + canvas.removeEventListener('mousemove', onCanvasMouseMove); }; }, [canvasRef]); diff --git a/src/utils.js b/src/utils.js index f2ec6906cdfd1..8105224d4a935 100644 --- a/src/utils.js +++ b/src/utils.js @@ -7,7 +7,7 @@ import type { Milliseconds, ReactPriority, ReactProfilerData, -} from '../types'; +} from './types'; // TODO Batch duration probably shouldn't include delayed passive effects? // It should probably end with the layout effect. From 6379a2e051afc92df7f0c6a760b764178bc5aa02 Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Wed, 17 Jun 2020 15:32:50 +0800 Subject: [PATCH 011/116] Add type annotations (2/n) (#8) --- .flowconfig | 1 + src/App.js | 92 ++++++++++++-------- src/EventTooltip.js | 57 ++++++++++-- src/constants.js | 4 +- src/context/useContextMenu.js | 9 +- src/contexts.js | 8 -- src/{ => graveyard}/SelectedEvent.js | 0 src/{ => graveyard}/SelectedEvent.module.css | 0 src/graveyard/contexts.js | 6 ++ src/graveyard/useDebounce.js | 32 +++++++ src/preprocessData.js | 39 +++++++-- src/types.js | 19 +++- src/useDebounce.js | 34 -------- src/usePanAndZoom.js | 20 ++--- src/useSmartTooltip.js | 10 ++- 15 files changed, 215 insertions(+), 116 deletions(-) delete mode 100644 src/contexts.js rename src/{ => graveyard}/SelectedEvent.js (100%) rename src/{ => graveyard}/SelectedEvent.module.css (100%) create mode 100644 src/graveyard/contexts.js create mode 100644 src/graveyard/useDebounce.js delete mode 100644 src/useDebounce.js diff --git a/.flowconfig b/.flowconfig index 1fed445333e85..042c3ca7f8d4b 100644 --- a/.flowconfig +++ b/.flowconfig @@ -1,4 +1,5 @@ [ignore] +./src/graveyard [include] diff --git a/src/App.js b/src/App.js index 069dafb8ea53f..769fc56628ba6 100644 --- a/src/App.js +++ b/src/App.js @@ -1,6 +1,7 @@ // @flow import type { TimelineEvent } from './speedscope/import/chrome'; +import type { PanAndZoomState } from './usePanAndZoom'; import { copy } from 'clipboard-js'; import React, { @@ -12,18 +13,16 @@ import React, { } from 'react'; import { unstable_batchedUpdates } from 'react-dom'; import memoize from 'memoize-one'; -import usePanAndZoom from './usePanAndZoom'; -import { getCanvasContext } from './canvasUtils'; -import prettyMilliseconds from 'pretty-ms'; -import { getBatchRange } from './utils'; -import { +import usePanAndZoom, { durationToWidth, positionToTimestamp, timestampToPosition, } from './usePanAndZoom'; +import { getCanvasContext } from './canvasUtils'; +import prettyMilliseconds from 'pretty-ms'; +import { getBatchRange } from './utils'; import useInteractiveEvents from './useInteractiveEvents'; import EventTooltip from './EventTooltip'; -import SelectedEvent from './SelectedEvent'; import preprocessData from './preprocessData'; import preprocessFlamechart from './preprocessFlamechart'; import styles from './App.css'; @@ -44,12 +43,7 @@ import { MARKER_HEIGHT, MARKER_TICK_HEIGHT, } from './constants'; -import { - ContextMenu, - ContextMenuItem, - RegistryContext, - useContextMenu, -} from './context'; +import { ContextMenu, ContextMenuItem, useContextMenu } from './context'; import JSON_PATH from 'url:../static/small-devtools.json'; //import JSON_PATH from 'url:../static/initial-render.json'; @@ -59,10 +53,19 @@ const CONTEXT_MENU_ID = 'canvas'; import type { FlamechartData, ReactEvent, + ReactHoverContextInfo, ReactMeasure, + ReactPriority, ReactProfilerData, } from './types'; +type ContextMenuContextData = {| + data: ReactProfilerData | null, + flamechart: FlamechartData | null, + hoveredEvent: ReactHoverContextInfo | null, + state: PanAndZoomState, +|}; + const REACT_PRIORITIES = ['unscheduled', 'high', 'normal', 'low']; const ROW_CSS_PIXELS_HEIGHT = 16; @@ -100,7 +103,12 @@ function getTimeTickInterval(zoomLevel) { return interval; } -function getHoveredEvent(schedulerCanvasHeight, data, flamechart, state) { +function getHoveredEvent( + schedulerCanvasHeight: number, + data: ReactProfilerData | null, + flamechart: FlamechartData | null, + state: PanAndZoomState +): ReactHoverContextInfo | null { const { canvasMouseX, canvasMouseY, offsetY } = state; if (canvasMouseX < LABEL_FIXED_WIDTH || canvasMouseY < HEADER_HEIGHT_FIXED) { @@ -112,7 +120,7 @@ function getHoveredEvent(schedulerCanvasHeight, data, flamechart, state) { let adjustedCanvasMouseY = canvasMouseY - HEADER_HEIGHT_FIXED + offsetY; let priorityMinY = HEADER_HEIGHT_FIXED; let priorityIndex = null; - let priority = null; + let priority: ReactPriority = 'unscheduled'; for (let index = 0; index < REACT_PRIORITIES.length; index++) { priority = REACT_PRIORITIES[index]; @@ -422,14 +430,14 @@ const renderReact = ({ // TODO Passing "state" directly breaks memoization for e.g. mouse moves const renderCanvas = memoize( ( - data, - flamechart, - canvas, - canvasWidth, - canvasHeight, - schedulerCanvasHeight, - state, - hoveredEvent + data: ReactProfilerData, + flamechart: FlamechartData | null, + canvas: HTMLCanvasElement | null, + canvasWidth: number, + canvasHeight: number, + schedulerCanvasHeight: number, + state: PanAndZoomState, + hoveredEvent: ReactHoverContextInfo | null ) => { const { offsetX, offsetY, zoomLevel } = state; @@ -684,9 +692,13 @@ const renderCanvas = memoize( ); const cachedPriorityHeights = new Map(); -const getPriorityHeight = (data, priority) => { +const getPriorityHeight = ( + data: ReactProfilerData, + priority: ReactPriority +): number => { if (cachedPriorityHeights.has(priority)) { - return cachedPriorityHeights.get(priority); + // We know the value must be present because we've just checked. + return ((cachedPriorityHeights.get(priority): any): number); } else { const numMeasures = data[priority].maxNestedMeasures; const events = data[priority].events; @@ -756,7 +768,7 @@ function App() { return (
- {({ height, width }) => ( + {({ height, width }: { height: number, width: number }) => ( { +const copySummary = (data: ReactProfilerData | null, measure: ReactMeasure) => { const { batchUID, duration, priority, timestamp, type } = measure; const [startTime, stopTime] = getBatchRange(batchUID, priority, data); @@ -785,28 +797,36 @@ const copySummary = (data, measure) => { ); }; -const zoomToBatch = (data, measure, state) => { +const zoomToBatch = ( + data: ReactProfilerData | null, + measure: ReactMeasure, + state: PanAndZoomState +) => { + const { zoomTo } = state; + if (!data || !zoomTo) { + return; + } const { batchUID, priority } = measure; const [startTime, stopTime] = getBatchRange(batchUID, priority, data); - - state.zoomTo(startTime, stopTime); + zoomTo(startTime, stopTime); }; -type Props = {| - data: any, // TODO: Fix - flamechart: FlamechartData, +type AutoSizedCanvasProps = {| + data: ReactProfilerData | null, + flamechart: FlamechartData | null, height: number, schedulerCanvasHeight: number, width: number, |}; + function AutoSizedCanvas({ data, flamechart, height, schedulerCanvasHeight, width, -}: Props) { - const canvasRef = useRef(null); +}: AutoSizedCanvasProps) { + const canvasRef = useRef(null); const state = usePanAndZoom({ canvasRef, @@ -830,7 +850,7 @@ function AutoSizedCanvas({ ); const [isContextMenuShown, setIsContextMenuShown] = useState(false); - useContextMenu({ + useContextMenu({ data: { data, flamechart, @@ -866,7 +886,7 @@ function AutoSizedCanvas({ width={width} /> - {({ data, hoveredEvent }) => { + {({ data, hoveredEvent }: ContextMenuContextData) => { if (hoveredEvent == null) { return null; } diff --git a/src/EventTooltip.js b/src/EventTooltip.js index fbe6b45eb8b82..8a1c3c5fc1a8a 100644 --- a/src/EventTooltip.js +++ b/src/EventTooltip.js @@ -1,5 +1,15 @@ // @flow +import type { PanAndZoomState } from './usePanAndZoom'; +import type { FlamechartFrame } from './speedscope/lib/flamechart'; +import type { + ReactEvent, + ReactMeasure, + ReactProfilerData, + ReactHoverContextInfo, + Return, +} from './types'; + import prettyMilliseconds from 'pretty-ms'; import React, { Fragment, useLayoutEffect, useRef } from 'react'; import { COLORS } from './constants'; @@ -9,7 +19,13 @@ import styles from './EventTooltip.css'; const TOOLTIP_OFFSET = 4; -export default function EventTooltip({ data, hoveredEvent, state }) { +type Props = {| + data: ReactProfilerData | null, + hoveredEvent: ReactHoverContextInfo | null, + state: PanAndZoomState, +|}; + +export default function EventTooltip({ data, hoveredEvent, state }: Props) { const { canvasMouseY, canvasMouseX } = state; const tooltipRef = useSmartTooltip({ @@ -85,12 +101,13 @@ export default function EventTooltip({ data, hoveredEvent, state }) { tooltipRef={tooltipRef} /> ); - } else { - return null; } + return null; } -function formatComponentStack(componentStack) { +declare function formatComponentStack(componentStack: null): null; +declare function formatComponentStack(componentStack: string): string; +function formatComponentStack(componentStack: string | null): string | null { if (componentStack == null) { return null; } @@ -104,7 +121,15 @@ function formatComponentStack(componentStack) { return lines.join('\n'); } -const TooltipFlamechartNode = ({ data, flamechartNode, tooltipRef }) => { +const TooltipFlamechartNode = ({ + data, + flamechartNode, + tooltipRef, +}: { + data: ReactProfilerData | null, + flamechartNode: FlamechartFrame, + tooltipRef: Return, +}) => { const { end, node, start } = flamechartNode; const { col, file, line, name } = node.frame; return ( @@ -126,7 +151,17 @@ const TooltipFlamechartNode = ({ data, flamechartNode, tooltipRef }) => { ); }; -const TooltipReactEvent = ({ color, data, event, tooltipRef }) => { +const TooltipReactEvent = ({ + color, + data, + event, + tooltipRef, +}: { + color: string, + data: ReactProfilerData | null, + event: ReactEvent, + tooltipRef: Return, +}) => { const { componentName, componentStack, timestamp, type } = event; let label = null; @@ -176,7 +211,15 @@ const TooltipReactEvent = ({ color, data, event, tooltipRef }) => { ); }; -const TooltipReactMeasure = ({ data, measure, tooltipRef }) => { +const TooltipReactMeasure = ({ + data, + measure, + tooltipRef, +}: { + data: ReactProfilerData | null, + measure: ReactMeasure, + tooltipRef: Return, +}) => { const { batchUID, duration, priority, timestamp, type } = measure; let label = null; diff --git a/src/constants.js b/src/constants.js index 4db22538d2e98..c1080bd15d816 100644 --- a/src/constants.js +++ b/src/constants.js @@ -36,7 +36,7 @@ export const ZOOM_WHEEL_DELTA_THRESHOLD = 1; export const MIN_ZOOM_LEVEL = 0.25; export const MAX_ZOOM_LEVEL = 1000; -export const COLORS = { +export const COLORS = Object.freeze({ BACKGROUND: '#ffffff', FLAME_GRAPH: '#fff79f', FLAME_GRAPH_HOVER: '#ffe900', @@ -69,4 +69,4 @@ export const COLORS = { REACT_WORK_BORDER: '#ffffff', TIME_MARKER_LINE: '#CAD6DE', TIME_MARKER_LABEL: '#18212b', -}; +}); diff --git a/src/context/useContextMenu.js b/src/context/useContextMenu.js index 3b2e3d2079ebe..f231bde4b8934 100644 --- a/src/context/useContextMenu.js +++ b/src/context/useContextMenu.js @@ -1,21 +1,22 @@ // @flow -import { useContext, useEffect } from 'react'; +import { useContext, useEffect, useRef } from 'react'; import { RegistryContext } from './Contexts'; import type { ElementRef } from 'react'; import type { OnChangeFn } from './Contexts'; +import type { Return } from '../types'; -export default function useContextMenu({ +export default function useContextMenu({ data, id, onChange, ref, }: {| - data: Object, // TODO: Type this? + data: T, id: string, onChange: OnChangeFn, - ref: {| current: HTMLElement | null |}, + ref: Return, |}) { const { showMenu } = useContext(RegistryContext); diff --git a/src/contexts.js b/src/contexts.js deleted file mode 100644 index 7452ff4a780b0..0000000000000 --- a/src/contexts.js +++ /dev/null @@ -1,8 +0,0 @@ -// @flow - -// import { createContext } from 'react'; - -// TODO: Figure out what these contexts are for. They were added in the -// prototype but were unused. -// export const PriorityContext = createContext(null); -// export const TimeRangeContext = createContext([0, 0]); diff --git a/src/SelectedEvent.js b/src/graveyard/SelectedEvent.js similarity index 100% rename from src/SelectedEvent.js rename to src/graveyard/SelectedEvent.js diff --git a/src/SelectedEvent.module.css b/src/graveyard/SelectedEvent.module.css similarity index 100% rename from src/SelectedEvent.module.css rename to src/graveyard/SelectedEvent.module.css diff --git a/src/graveyard/contexts.js b/src/graveyard/contexts.js new file mode 100644 index 0000000000000..f02f24b30cfb6 --- /dev/null +++ b/src/graveyard/contexts.js @@ -0,0 +1,6 @@ +// @flow + +import { createContext } from 'react'; + +export const PriorityContext = createContext(null); +export const TimeRangeContext = createContext([0, 0]); diff --git a/src/graveyard/useDebounce.js b/src/graveyard/useDebounce.js new file mode 100644 index 0000000000000..4d1fb606f58ff --- /dev/null +++ b/src/graveyard/useDebounce.js @@ -0,0 +1,32 @@ +// @flow + +import { useDebugValue, useEffect, useState } from 'react'; + +// Below copied from https://usehooks.com/ +export default function useDebounce(value: T, delay: number): T { + // State and setters for debounced value + const [debouncedValue, setDebouncedValue] = useState(value); + + // Show the value in DevTools + useDebugValue(debouncedValue); + + useEffect( + () => { + // Update debounced value after delay + const handler = setTimeout(() => { + setDebouncedValue(value); + }, delay); + + // Cancel the timeout if value changes (also on delay change or unmount) + // This is how we prevent debounced value from updating if value is changed ... + // .. within the delay period. Timeout gets cleared and restarted. + return () => { + clearTimeout(handler); + }; + }, + [value, delay] // Only re-call effect if value or delay changes + ); + + return debouncedValue; +} +// Above copied from https://usehooks.com/ diff --git a/src/preprocessData.js b/src/preprocessData.js index 7b8c3c8397873..2b88d08563921 100644 --- a/src/preprocessData.js +++ b/src/preprocessData.js @@ -3,7 +3,10 @@ import type { TimelineEvent } from './speedscope/import/chrome'; import type { + Milliseconds, BatchUID, + ReactEvent, + ReactMeasureType, ReactPriority, ReactProfilerData, ReactProfilerDataPriority, @@ -11,10 +14,19 @@ import type { // TODO Combine yields/starts that are closer than some threshold with the previous event to reduce renders. +// TODO: Figure out what this is +type StackElement = {| + type: ReactMeasureType, + depth: number, + index: number, + startTime: Milliseconds, + stopTime?: Milliseconds, +|}; + type Metadata = {| nextRenderShouldGenerateNewBatchID: boolean, batchUID: BatchUID, - +stack: Array, + +stack: StackElement[], |}; export default function reactProfilerProcessor( @@ -45,12 +57,12 @@ export default function reactProfilerProcessor( }, }; - let currentMetadata: ?Metadata = null; - let currentPriority = 'unscheduled'; - let currentProfilerDataGroup = null; + let currentMetadata: Metadata | null = null; + let currentPriority: ReactPriority = 'unscheduled'; + let currentProfilerDataGroup: ReactProfilerDataPriority | null = null; let uidCounter = 0; - const metadata = { + const metadata: {| [priority: ReactPriority]: Metadata |} = { high: { batchUID: 0, nextRenderShouldGenerateNewBatchID: true, @@ -91,13 +103,16 @@ export default function reactProfilerProcessor( } const { stack } = currentMetadata; if (stack.length > 0) { - const { depth, type } = stack[stack.length - 1]; + const { depth, type } = (stack[stack.length - 1]: StackElement); return type === 'render-idle' ? depth : depth + 1; } return 0; }; - const markWorkCompleted = (type, stopTime) => { + const markWorkCompleted = ( + type: ReactMeasureType, + stopTime: Milliseconds + ) => { if (!currentMetadata) { return; } @@ -130,7 +145,10 @@ export default function reactProfilerProcessor( } }; - const markWorkStarted = (type, startTime) => { + const markWorkStarted = (type: ReactMeasureType, startTime: Milliseconds) => { + if (!currentMetadata || !currentProfilerDataGroup) { + return; + } const { batchUID, stack } = currentMetadata; const index = currentProfilerDataGroup.measures.length; @@ -159,6 +177,9 @@ export default function reactProfilerProcessor( }; const throwIfIncomplete = type => { + if (!currentMetadata) { + return; + } const { stack } = currentMetadata; const lastIndex = stack.length - 1; if (lastIndex >= 0) { @@ -298,7 +319,7 @@ export default function reactProfilerProcessor( ['unscheduled', 'high', 'normal', 'low'].forEach(priority => { const { events, measures } = reactProfilerData[priority]; if (events.length > 0) { - const { timestamp } = events[events.length - 1]; + const { timestamp } = (events[events.length - 1]: ReactEvent); reactProfilerData.duration = Math.max( reactProfilerData.duration, timestamp diff --git a/src/types.js b/src/types.js index 92a9c9b013acb..d1c8d2077d80e 100644 --- a/src/types.js +++ b/src/types.js @@ -1,6 +1,15 @@ // @flow -import { Flamechart } from './speedscope/lib/flamechart'; +import type { Flamechart, FlamechartFrame } from './speedscope/lib/flamechart'; + +// Type utilities + +// Source: https://github.com/facebook/flow/issues/4002#issuecomment-323612798 +type Return_) => R> = R; +/** Get return type of a function. */ +export type Return = Return_<*, T>; + +// Project types export type Milliseconds = number; @@ -45,6 +54,8 @@ export type ReactProfilerDataPriority = {| |}; export type ReactProfilerData = {| + startTime: number, + duration: number, unscheduled: ReactProfilerDataPriority, high: ReactProfilerDataPriority, normal: ReactProfilerDataPriority, @@ -54,9 +65,9 @@ export type ReactProfilerData = {| export type ReactHoverContextInfo = {| event: ReactEvent | null, measure: ReactMeasure | null, - priorityIndex: number, - reactProfilerData: ReactProfilerData, - zeroAt: Milliseconds, + priorityIndex: number | null, + data: ReactProfilerData | null, + flamechartNode: FlamechartFrame | null, |}; export type FlamechartData = Flamechart; diff --git a/src/useDebounce.js b/src/useDebounce.js deleted file mode 100644 index 93947aaf08a2f..0000000000000 --- a/src/useDebounce.js +++ /dev/null @@ -1,34 +0,0 @@ -// @flow - -// TODO: Remove if unused - -// import { useDebugValue, useEffect, useState } from 'react'; - -// // Below copied from https://usehooks.com/ -// export default function useDebounce(value: T, delay: number): T { -// // State and setters for debounced value -// const [debouncedValue, setDebouncedValue] = useState(value); - -// // Show the value in DevTools -// useDebugValue(debouncedValue); - -// useEffect( -// () => { -// // Update debounced value after delay -// const handler = setTimeout(() => { -// setDebouncedValue(value); -// }, delay); - -// // Cancel the timeout if value changes (also on delay change or unmount) -// // This is how we prevent debounced value from updating if value is changed ... -// // .. within the delay period. Timeout gets cleared and restarted. -// return () => { -// clearTimeout(handler); -// }; -// }, -// [value, delay] // Only re-call effect if value or delay changes -// ); - -// return debouncedValue; -// } -// // Above copied from https://usehooks.com/ diff --git a/src/usePanAndZoom.js b/src/usePanAndZoom.js index 01c4ce89402eb..fa9097c6dcbb3 100644 --- a/src/usePanAndZoom.js +++ b/src/usePanAndZoom.js @@ -11,7 +11,7 @@ import { ZOOM_WHEEL_DELTA_THRESHOLD, } from './constants'; -type State = {| +export type PanAndZoomState = {| canvasHeight: number, canvasWidth: number, canvasMouseX: number, @@ -28,7 +28,7 @@ type State = {| zoomTo: null | ((startTime: number, endTime: number) => void), |}; -const initialState: State = { +const initialState: PanAndZoomState = { canvasHeight: 0, canvasWidth: 0, canvasMouseX: 0, @@ -46,23 +46,23 @@ const initialState: State = { }; // TODO Account for fixed label width -export function positionToTimestamp(position: number, state: State) { +export function positionToTimestamp(position: number, state: PanAndZoomState) { return (position - state.fixedColumnWidth + state.offsetX) / state.zoomLevel; } // TODO Account for fixed label width -export function timestampToPosition(timestamp: number, state: State) { +export function timestampToPosition(timestamp: number, state: PanAndZoomState) { return timestamp * state.zoomLevel + state.fixedColumnWidth - state.offsetX; } -export function durationToWidth(duration: number, state: State) { +export function durationToWidth(duration: number, state: PanAndZoomState) { return Math.max( duration * state.zoomLevel - BAR_HORIZONTAL_SPACING, MIN_BAR_WIDTH ); } -function getMaxOffsetX(state: State) { +function getMaxOffsetX(state: PanAndZoomState) { return ( state.unscaledContentWidth * state.zoomLevel - state.canvasWidth + @@ -70,7 +70,7 @@ function getMaxOffsetX(state: State) { ); } -function getMaxOffsetY(state: State) { +function getMaxOffsetY(state: PanAndZoomState) { return ( state.unscaledContentHeight - state.canvasHeight + state.fixedHeaderHeight ); @@ -109,7 +109,7 @@ type ZoomToAction = {| |}; function reducer( - state: State, + state: PanAndZoomState, action: | InitializeAction | MouseDownAction @@ -117,7 +117,7 @@ function reducer( | MouseUpAction | WheelAction | ZoomToAction -): State { +): PanAndZoomState { switch (action.type) { case 'initialize': { const { payload } = action; @@ -276,7 +276,7 @@ function clamp(min: number, max: number, value: number): number { } type Props = {| - canvasRef: {| current: ?HTMLCanvasElement |}, + canvasRef: {| current: HTMLCanvasElement | null |}, canvasHeight: number, canvasWidth: number, fixedColumnWidth: number, diff --git a/src/useSmartTooltip.js b/src/useSmartTooltip.js index c7a1484f60e71..2b877b87cf419 100644 --- a/src/useSmartTooltip.js +++ b/src/useSmartTooltip.js @@ -4,8 +4,14 @@ import { useLayoutEffect, useRef } from 'react'; const TOOLTIP_OFFSET = 4; -export default function useSmartTooltip({ mouseX, mouseY }) { - const ref = useRef(null); +export default function useSmartTooltip({ + mouseX, + mouseY, +}: { + mouseX: number, + mouseY: number, +}) { + const ref = useRef(null); useLayoutEffect(() => { const element = ref.current; From 178910bcd07f98e2f4f631946b6b2f1ed68d5592 Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Mon, 22 Jun 2020 14:18:20 +0800 Subject: [PATCH 012/116] Add Jest and configs Based on CRA's setup. --- .babelrc | 3 + jest.config.js | 5 + package.json | 7 + setupTests.js | 5 + yarn.lock | 3155 +++++++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 3145 insertions(+), 30 deletions(-) create mode 100644 .babelrc create mode 100644 jest.config.js create mode 100644 setupTests.js diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000000000..7aa30766abb68 --- /dev/null +++ b/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": [["react-app", { "flow": true, "typescript": false }]] +} diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 0000000000000..30e44cbe58974 --- /dev/null +++ b/jest.config.js @@ -0,0 +1,5 @@ +module.exports = { + moduleNameMapper: { + '\\.css$': 'identity-obj-proxy', + }, +}; diff --git a/package.json b/package.json index 30a3875b03642..5fbee0df1d298 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,14 @@ "scheduler": "^0.19.1" }, "devDependencies": { + "@babel/core": "^7.10.3", + "@testing-library/jest-dom": "^5.10.1", + "@testing-library/react": "^10.3.0", + "babel-jest": "^26.0.1", + "babel-preset-react-app": "^9.1.2", "flow-bin": "^0.127.0", + "identity-obj-proxy": "^3.0.0", + "jest": "^26.0.1", "parcel": "2.0.0-alpha.3.2", "postcss-modules": "^2.0.0", "prettier": "^1.19.1" diff --git a/setupTests.js b/setupTests.js new file mode 100644 index 0000000000000..8f2609b7b3e0e --- /dev/null +++ b/setupTests.js @@ -0,0 +1,5 @@ +// jest-dom adds custom jest matchers for asserting on DOM nodes. +// allows you to do things like: +// expect(element).toHaveTextContent(/react/i) +// learn more: https://github.com/testing-library/jest-dom +import '@testing-library/jest-dom'; diff --git a/yarn.lock b/yarn.lock index ac24575e933b4..d963933b09203 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9,6 +9,44 @@ dependencies: "@babel/highlight" "^7.0.0" +"@babel/code-frame@^7.10.3", "@babel/code-frame@^7.8.3": + version "7.10.3" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.3.tgz#324bcfd8d35cd3d47dae18cde63d752086435e9a" + integrity sha512-fDx9eNW0qz0WkUeqL6tXEXzVlPh6Y5aCDEZesl0xBGA8ndRukX91Uk44ZqnkECp01NAZUdCAl+aiQNGi0k88Eg== + dependencies: + "@babel/highlight" "^7.10.3" + +"@babel/compat-data@^7.10.1", "@babel/compat-data@^7.9.0": + version "7.10.3" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.10.3.tgz#9af3e033f36e8e2d6e47570db91e64a846f5d382" + integrity sha512-BDIfJ9uNZuI0LajPfoYV28lX8kyCPMHY6uY4WH1lJdcicmAfxCK5ASzaeV0D/wsUaRH/cLk+amuxtC37sZ8TUg== + dependencies: + browserslist "^4.12.0" + invariant "^2.2.4" + semver "^5.5.0" + +"@babel/core@7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.9.0.tgz#ac977b538b77e132ff706f3b8a4dbad09c03c56e" + integrity sha512-kWc7L0fw1xwvI0zi8OKVBuxRVefwGOrKSQMvrQ3dW+bIIavBY3/NpXmpjMy7bQnLgwgzWQZ8TlM57YHpHNHz4w== + dependencies: + "@babel/code-frame" "^7.8.3" + "@babel/generator" "^7.9.0" + "@babel/helper-module-transforms" "^7.9.0" + "@babel/helpers" "^7.9.0" + "@babel/parser" "^7.9.0" + "@babel/template" "^7.8.6" + "@babel/traverse" "^7.9.0" + "@babel/types" "^7.9.0" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.1" + json5 "^2.1.2" + lodash "^4.17.13" + resolve "^1.3.2" + semver "^5.4.1" + source-map "^0.5.0" + "@babel/core@^7.0.0": version "7.7.7" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.7.7.tgz#ee155d2e12300bcc0cff6a8ad46f2af5063803e9" @@ -29,6 +67,28 @@ semver "^5.4.1" source-map "^0.5.0" +"@babel/core@^7.1.0", "@babel/core@^7.10.3", "@babel/core@^7.7.5": + version "7.10.3" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.10.3.tgz#73b0e8ddeec1e3fdd7a2de587a60e17c440ec77e" + integrity sha512-5YqWxYE3pyhIi84L84YcwjeEgS+fa7ZjK6IBVGTjDVfm64njkR2lfDhVR5OudLk8x2GK59YoSyVv+L/03k1q9w== + dependencies: + "@babel/code-frame" "^7.10.3" + "@babel/generator" "^7.10.3" + "@babel/helper-module-transforms" "^7.10.1" + "@babel/helpers" "^7.10.1" + "@babel/parser" "^7.10.3" + "@babel/template" "^7.10.3" + "@babel/traverse" "^7.10.3" + "@babel/types" "^7.10.3" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.1" + json5 "^2.1.2" + lodash "^4.17.13" + resolve "^1.3.2" + semver "^5.4.1" + source-map "^0.5.0" + "@babel/generator@^7.0.0", "@babel/generator@^7.3.3", "@babel/generator@^7.7.4", "@babel/generator@^7.7.7": version "7.7.7" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.7.7.tgz#859ac733c44c74148e1a72980a64ec84b85f4f45" @@ -39,6 +99,23 @@ lodash "^4.17.13" source-map "^0.5.0" +"@babel/generator@^7.10.3", "@babel/generator@^7.9.0": + version "7.10.3" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.10.3.tgz#32b9a0d963a71d7a54f5f6c15659c3dbc2a523a5" + integrity sha512-drt8MUHbEqRzNR0xnF8nMehbY11b1SDkRw03PSNH/3Rb2Z35oxkddVSi3rcaak0YJQ86PCuE7Qx1jSFhbLNBMA== + dependencies: + "@babel/types" "^7.10.3" + jsesc "^2.5.1" + lodash "^4.17.13" + source-map "^0.5.0" + +"@babel/helper-annotate-as-pure@^7.10.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.1.tgz#f6d08acc6f70bbd59b436262553fb2e259a1a268" + integrity sha512-ewp3rvJEwLaHgyWGe4wQssC2vjks3E80WiUe2BpMb0KhreTjMROCbxXcEovTrbeGVdQct5VjQfrv9EgC+xMzCw== + dependencies: + "@babel/types" "^7.10.1" + "@babel/helper-annotate-as-pure@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.7.4.tgz#bb3faf1e74b74bd547e867e48f551fa6b098b6ce" @@ -46,6 +123,14 @@ dependencies: "@babel/types" "^7.7.4" +"@babel/helper-builder-binary-assignment-operator-visitor@^7.10.1": + version "7.10.3" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.3.tgz#4e9012d6701bef0030348d7f9c808209bd3e8687" + integrity sha512-lo4XXRnBlU6eRM92FkiZxpo1xFLmv3VsPFk61zJKMm7XYJfwqXHsYJTY6agoc4a3L8QPw1HqWehO18coZgbT6A== + dependencies: + "@babel/helper-explode-assignable-expression" "^7.10.3" + "@babel/types" "^7.10.3" + "@babel/helper-builder-binary-assignment-operator-visitor@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.7.4.tgz#5f73f2b28580e224b5b9bd03146a4015d6217f5f" @@ -54,6 +139,23 @@ "@babel/helper-explode-assignable-expression" "^7.7.4" "@babel/types" "^7.7.4" +"@babel/helper-builder-react-jsx-experimental@^7.10.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.10.1.tgz#9a7d58ad184d3ac3bafb1a452cec2bad7e4a0bc8" + integrity sha512-irQJ8kpQUV3JasXPSFQ+LCCtJSc5ceZrPFVj6TElR6XCHssi3jV8ch3odIrNtjJFRZZVbrOEfJMI79TPU/h1pQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.1" + "@babel/helper-module-imports" "^7.10.1" + "@babel/types" "^7.10.1" + +"@babel/helper-builder-react-jsx@^7.10.3": + version "7.10.3" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.10.3.tgz#62c4b7bb381153a0a5f8d83189b94b9fb5384fc5" + integrity sha512-vkxmuFvmovtqTZknyMGj9+uQAZzz5Z9mrbnkJnPkaYGfKTaSsYcjQdXP0lgrWLVh8wU6bCjOmXOpx+kqUi+S5Q== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.1" + "@babel/types" "^7.10.3" + "@babel/helper-builder-react-jsx@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.7.4.tgz#da188d247508b65375b2c30cf59de187be6b0c66" @@ -71,6 +173,29 @@ "@babel/traverse" "^7.7.4" "@babel/types" "^7.7.4" +"@babel/helper-compilation-targets@^7.8.7": + version "7.10.2" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.10.2.tgz#a17d9723b6e2c750299d2a14d4637c76936d8285" + integrity sha512-hYgOhF4To2UTB4LTaZepN/4Pl9LD4gfbJx8A34mqoluT8TLbof1mhUlYuNWTEebONa8+UlCC4X0TEXu7AOUyGA== + dependencies: + "@babel/compat-data" "^7.10.1" + browserslist "^4.12.0" + invariant "^2.2.4" + levenary "^1.1.1" + semver "^5.5.0" + +"@babel/helper-create-class-features-plugin@^7.10.3", "@babel/helper-create-class-features-plugin@^7.8.3": + version "7.10.3" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.3.tgz#2783daa6866822e3d5ed119163b50f0fc3ae4b35" + integrity sha512-iRT9VwqtdFmv7UheJWthGc/h2s7MqoweBF9RUj77NFZsg9VfISvBTum3k6coAhJ8RWv2tj3yUjA03HxPd0vfpQ== + dependencies: + "@babel/helper-function-name" "^7.10.3" + "@babel/helper-member-expression-to-functions" "^7.10.3" + "@babel/helper-optimise-call-expression" "^7.10.3" + "@babel/helper-plugin-utils" "^7.10.3" + "@babel/helper-replace-supers" "^7.10.1" + "@babel/helper-split-export-declaration" "^7.10.1" + "@babel/helper-create-class-features-plugin@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.7.4.tgz#fce60939fd50618610942320a8d951b3b639da2d" @@ -83,6 +208,15 @@ "@babel/helper-replace-supers" "^7.7.4" "@babel/helper-split-export-declaration" "^7.7.4" +"@babel/helper-create-regexp-features-plugin@^7.10.1", "@babel/helper-create-regexp-features-plugin@^7.8.3": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.10.1.tgz#1b8feeab1594cbcfbf3ab5a3bbcabac0468efdbd" + integrity sha512-Rx4rHS0pVuJn5pJOqaqcZR4XSgeF9G/pO/79t+4r7380tXFJdzImFnxMU19f83wjSrmKHq6myrM10pFHTGzkUA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.1" + "@babel/helper-regex" "^7.10.1" + regexpu-core "^4.7.0" + "@babel/helper-create-regexp-features-plugin@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.7.4.tgz#6d5762359fd34f4da1500e4cff9955b5299aaf59" @@ -91,6 +225,15 @@ "@babel/helper-regex" "^7.4.4" regexpu-core "^4.6.0" +"@babel/helper-define-map@^7.10.3": + version "7.10.3" + resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.10.3.tgz#d27120a5e57c84727b30944549b2dfeca62401a8" + integrity sha512-bxRzDi4Sin/k0drWCczppOhov1sBSdBvXJObM1NLHQzjhXhwRtn7aRWGvLJWCYbuu2qUk3EKs6Ci9C9ps8XokQ== + dependencies: + "@babel/helper-function-name" "^7.10.3" + "@babel/types" "^7.10.3" + lodash "^4.17.13" + "@babel/helper-define-map@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.7.4.tgz#2841bf92eb8bd9c906851546fe6b9d45e162f176" @@ -100,6 +243,14 @@ "@babel/types" "^7.7.4" lodash "^4.17.13" +"@babel/helper-explode-assignable-expression@^7.10.3": + version "7.10.3" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.10.3.tgz#9dc14f0cfa2833ea830a9c8a1c742b6e7461b05e" + integrity sha512-0nKcR64XrOC3lsl+uhD15cwxPvaB6QKUDlD84OT9C3myRbhJqTMYir69/RWItUvHpharv0eJ/wk7fl34ONSwZw== + dependencies: + "@babel/traverse" "^7.10.3" + "@babel/types" "^7.10.3" + "@babel/helper-explode-assignable-expression@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.7.4.tgz#fa700878e008d85dc51ba43e9fb835cddfe05c84" @@ -108,6 +259,15 @@ "@babel/traverse" "^7.7.4" "@babel/types" "^7.7.4" +"@babel/helper-function-name@^7.10.1", "@babel/helper-function-name@^7.10.3": + version "7.10.3" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.10.3.tgz#79316cd75a9fa25ba9787ff54544307ed444f197" + integrity sha512-FvSj2aiOd8zbeqijjgqdMDSyxsGHaMt5Tr0XjQsGKHD3/1FP3wksjnLAWzxw7lvXiej8W1Jt47SKTZ6upQNiRw== + dependencies: + "@babel/helper-get-function-arity" "^7.10.3" + "@babel/template" "^7.10.3" + "@babel/types" "^7.10.3" + "@babel/helper-function-name@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz#ab6e041e7135d436d8f0a3eca15de5b67a341a2e" @@ -117,6 +277,13 @@ "@babel/template" "^7.7.4" "@babel/types" "^7.7.4" +"@babel/helper-get-function-arity@^7.10.1", "@babel/helper-get-function-arity@^7.10.3": + version "7.10.3" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.3.tgz#3a28f7b28ccc7719eacd9223b659fdf162e4c45e" + integrity sha512-iUD/gFsR+M6uiy69JA6fzM5seno8oE85IYZdbVVEuQaZlEzMO2MXblh+KSPJgsZAUx0EEbWXU0yJaW7C9CdAVg== + dependencies: + "@babel/types" "^7.10.3" + "@babel/helper-get-function-arity@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz#cb46348d2f8808e632f0ab048172130e636005f0" @@ -124,6 +291,13 @@ dependencies: "@babel/types" "^7.7.4" +"@babel/helper-hoist-variables@^7.10.3": + version "7.10.3" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.3.tgz#d554f52baf1657ffbd7e5137311abc993bb3f068" + integrity sha512-9JyafKoBt5h20Yv1+BXQMdcXXavozI1vt401KBiRc2qzUepbVnd7ogVNymY1xkQN9fekGwfxtotH2Yf5xsGzgg== + dependencies: + "@babel/types" "^7.10.3" + "@babel/helper-hoist-variables@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.7.4.tgz#612384e3d823fdfaaf9fce31550fe5d4db0f3d12" @@ -131,6 +305,13 @@ dependencies: "@babel/types" "^7.7.4" +"@babel/helper-member-expression-to-functions@^7.10.1", "@babel/helper-member-expression-to-functions@^7.10.3": + version "7.10.3" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.10.3.tgz#bc3663ac81ac57c39148fef4c69bf48a77ba8dd6" + integrity sha512-q7+37c4EPLSjNb2NmWOjNwj0+BOyYlssuQ58kHEWk1Z78K5i8vTUsteq78HMieRPQSl/NtpQyJfdjt3qZ5V2vw== + dependencies: + "@babel/types" "^7.10.3" + "@babel/helper-member-expression-to-functions@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.7.4.tgz#356438e2569df7321a8326644d4b790d2122cb74" @@ -138,6 +319,13 @@ dependencies: "@babel/types" "^7.7.4" +"@babel/helper-module-imports@^7.10.1", "@babel/helper-module-imports@^7.8.3": + version "7.10.3" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.10.3.tgz#766fa1d57608e53e5676f23ae498ec7a95e1b11a" + integrity sha512-Jtqw5M9pahLSUWA+76nhK9OG8nwYXzhQzVIGFoNaHnXF/r4l7kz4Fl0UAW7B6mqC5myoJiBP5/YQlXQTMfHI9w== + dependencies: + "@babel/types" "^7.10.3" + "@babel/helper-module-imports@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.7.4.tgz#e5a92529f8888bf319a6376abfbd1cebc491ad91" @@ -145,6 +333,19 @@ dependencies: "@babel/types" "^7.7.4" +"@babel/helper-module-transforms@^7.10.1", "@babel/helper-module-transforms@^7.9.0": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.10.1.tgz#24e2f08ee6832c60b157bb0936c86bef7210c622" + integrity sha512-RLHRCAzyJe7Q7sF4oy2cB+kRnU4wDZY/H2xJFGof+M+SJEGhZsb+GFj5j1AD8NiSaVBJ+Pf0/WObiXu/zxWpFg== + dependencies: + "@babel/helper-module-imports" "^7.10.1" + "@babel/helper-replace-supers" "^7.10.1" + "@babel/helper-simple-access" "^7.10.1" + "@babel/helper-split-export-declaration" "^7.10.1" + "@babel/template" "^7.10.1" + "@babel/types" "^7.10.1" + lodash "^4.17.13" + "@babel/helper-module-transforms@^7.7.4", "@babel/helper-module-transforms@^7.7.5": version "7.7.5" resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.7.5.tgz#d044da7ffd91ec967db25cd6748f704b6b244835" @@ -157,6 +358,13 @@ "@babel/types" "^7.7.4" lodash "^4.17.13" +"@babel/helper-optimise-call-expression@^7.10.1", "@babel/helper-optimise-call-expression@^7.10.3": + version "7.10.3" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.3.tgz#f53c4b6783093195b0f69330439908841660c530" + integrity sha512-kT2R3VBH/cnSz+yChKpaKRJQJWxdGoc6SjioRId2wkeV3bK0wLLioFpJROrX0U4xr/NmxSSAWT/9Ih5snwIIzg== + dependencies: + "@babel/types" "^7.10.3" + "@babel/helper-optimise-call-expression@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.7.4.tgz#034af31370d2995242aa4df402c3b7794b2dcdf2" @@ -169,6 +377,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz#bbb3fbee98661c569034237cc03967ba99b4f250" integrity sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA== +"@babel/helper-plugin-utils@^7.10.1", "@babel/helper-plugin-utils@^7.10.3", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.10.3" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.3.tgz#aac45cccf8bc1873b99a85f34bceef3beb5d3244" + integrity sha512-j/+j8NAWUTxOtx4LKHybpSClxHoq6I91DQ/mKgAXn5oNUPIUiGppjPIX3TDtJWPrdfP9Kfl7e4fgVMiQR9VE/g== + "@babel/helper-regex@^7.0.0", "@babel/helper-regex@^7.4.4": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.5.5.tgz#0aa6824f7100a2e0e89c1527c23936c152cab351" @@ -176,6 +389,24 @@ dependencies: lodash "^4.17.13" +"@babel/helper-regex@^7.10.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.10.1.tgz#021cf1a7ba99822f993222a001cc3fec83255b96" + integrity sha512-7isHr19RsIJWWLLFn21ubFt223PjQyg1HY7CZEMRr820HttHPpVvrsIN3bUOo44DEfFV4kBXO7Abbn9KTUZV7g== + dependencies: + lodash "^4.17.13" + +"@babel/helper-remap-async-to-generator@^7.10.1", "@babel/helper-remap-async-to-generator@^7.10.3": + version "7.10.3" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.10.3.tgz#18564f8a6748be466970195b876e8bba3bccf442" + integrity sha512-sLB7666ARbJUGDO60ZormmhQOyqMX/shKBXZ7fy937s+3ID8gSrneMvKSSb+8xIM5V7Vn6uNVtOY1vIm26XLtA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.1" + "@babel/helper-wrap-function" "^7.10.1" + "@babel/template" "^7.10.3" + "@babel/traverse" "^7.10.3" + "@babel/types" "^7.10.3" + "@babel/helper-remap-async-to-generator@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.7.4.tgz#c68c2407350d9af0e061ed6726afb4fff16d0234" @@ -187,6 +418,16 @@ "@babel/traverse" "^7.7.4" "@babel/types" "^7.7.4" +"@babel/helper-replace-supers@^7.10.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.10.1.tgz#ec6859d20c5d8087f6a2dc4e014db7228975f13d" + integrity sha512-SOwJzEfpuQwInzzQJGjGaiG578UYmyi2Xw668klPWV5n07B73S0a9btjLk/52Mlcxa+5AdIYqws1KyXRfMoB7A== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.10.1" + "@babel/helper-optimise-call-expression" "^7.10.1" + "@babel/traverse" "^7.10.1" + "@babel/types" "^7.10.1" + "@babel/helper-replace-supers@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.7.4.tgz#3c881a6a6a7571275a72d82e6107126ec9e2cdd2" @@ -197,6 +438,14 @@ "@babel/traverse" "^7.7.4" "@babel/types" "^7.7.4" +"@babel/helper-simple-access@^7.10.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.10.1.tgz#08fb7e22ace9eb8326f7e3920a1c2052f13d851e" + integrity sha512-VSWpWzRzn9VtgMJBIWTZ+GP107kZdQ4YplJlCmIrjoLVSi/0upixezHCDG8kpPVTBJpKfxTH01wDhh+jS2zKbw== + dependencies: + "@babel/template" "^7.10.1" + "@babel/types" "^7.10.1" + "@babel/helper-simple-access@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.7.4.tgz#a169a0adb1b5f418cfc19f22586b2ebf58a9a294" @@ -205,6 +454,13 @@ "@babel/template" "^7.7.4" "@babel/types" "^7.7.4" +"@babel/helper-split-export-declaration@^7.10.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.1.tgz#c6f4be1cbc15e3a868e4c64a17d5d31d754da35f" + integrity sha512-UQ1LVBPrYdbchNhLwj6fetj46BcFwfS4NllJo/1aJsT+1dLTEnXJL0qHqtY7gPzF8S2fXBJamf1biAXV3X077g== + dependencies: + "@babel/types" "^7.10.1" + "@babel/helper-split-export-declaration@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz#57292af60443c4a3622cf74040ddc28e68336fd8" @@ -212,6 +468,21 @@ dependencies: "@babel/types" "^7.7.4" +"@babel/helper-validator-identifier@^7.10.3": + version "7.10.3" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.3.tgz#60d9847f98c4cea1b279e005fdb7c28be5412d15" + integrity sha512-bU8JvtlYpJSBPuj1VUmKpFGaDZuLxASky3LhaKj3bmpSTY6VWooSM8msk+Z0CZoErFye2tlABF6yDkT3FOPAXw== + +"@babel/helper-wrap-function@^7.10.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.10.1.tgz#956d1310d6696257a7afd47e4c42dfda5dfcedc9" + integrity sha512-C0MzRGteVDn+H32/ZgbAv5r56f2o1fZSA/rj/TYo8JEJNHg+9BdSmKBUND0shxWRztWhjlT2cvHYuynpPsVJwQ== + dependencies: + "@babel/helper-function-name" "^7.10.1" + "@babel/template" "^7.10.1" + "@babel/traverse" "^7.10.1" + "@babel/types" "^7.10.1" + "@babel/helper-wrap-function@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.7.4.tgz#37ab7fed5150e22d9d7266e830072c0cdd8baace" @@ -222,6 +493,15 @@ "@babel/traverse" "^7.7.4" "@babel/types" "^7.7.4" +"@babel/helpers@^7.10.1", "@babel/helpers@^7.9.0": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.10.1.tgz#a6827b7cb975c9d9cef5fd61d919f60d8844a973" + integrity sha512-muQNHF+IdU6wGgkaJyhhEmI54MOZBKsFfsXFhboz1ybwJ1Kl7IHlbm2a++4jwrmY5UYsgitt5lfqo1wMFcHmyw== + dependencies: + "@babel/template" "^7.10.1" + "@babel/traverse" "^7.10.1" + "@babel/types" "^7.10.1" + "@babel/helpers@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.7.4.tgz#62c215b9e6c712dadc15a9a0dcab76c92a940302" @@ -240,11 +520,25 @@ esutils "^2.0.2" js-tokens "^4.0.0" +"@babel/highlight@^7.10.3": + version "7.10.3" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.3.tgz#c633bb34adf07c5c13156692f5922c81ec53f28d" + integrity sha512-Ih9B/u7AtgEnySE2L2F0Xm0GaM729XqqLfHkalTsbjXGyqmf/6M0Cu0WpvqueUlW+xk88BHw9Nkpj49naU+vWw== + dependencies: + "@babel/helper-validator-identifier" "^7.10.3" + chalk "^2.0.0" + js-tokens "^4.0.0" + "@babel/parser@^7.0.0", "@babel/parser@^7.7.4", "@babel/parser@^7.7.7": version "7.7.7" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.7.tgz#1b886595419cf92d811316d5b715a53ff38b4937" integrity sha512-WtTZMZAZLbeymhkd/sEaPD8IQyGAhmuTuvTzLiCFM7iXiVdY0gc0IaI+cW0fh1BnSMbJSzXX6/fHllgHKwHhXw== +"@babel/parser@^7.1.0", "@babel/parser@^7.10.3", "@babel/parser@^7.9.0": + version "7.10.3" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.10.3.tgz#7e71d892b0d6e7d04a1af4c3c79d72c1f10f5315" + integrity sha512-oJtNJCMFdIMwXGmx+KxuaD7i3b8uS7TTFYW/FNG2BT8m+fmGHoiPYoH0Pe3gya07WuFmM5FCDIr1x0irkD/hyA== + "@babel/plugin-proposal-async-generator-functions@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.7.4.tgz#0351c5ac0a9e927845fffd5b82af476947b7ce6d" @@ -254,6 +548,32 @@ "@babel/helper-remap-async-to-generator" "^7.7.4" "@babel/plugin-syntax-async-generators" "^7.7.4" +"@babel/plugin-proposal-async-generator-functions@^7.8.3": + version "7.10.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.3.tgz#5a02453d46e5362e2073c7278beab2e53ad7d939" + integrity sha512-WUUWM7YTOudF4jZBAJIW9D7aViYC/Fn0Pln4RIHlQALyno3sXSjqmTA4Zy1TKC2D49RCR8Y/Pn4OIUtEypK3CA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.3" + "@babel/helper-remap-async-to-generator" "^7.10.3" + "@babel/plugin-syntax-async-generators" "^7.8.0" + +"@babel/plugin-proposal-class-properties@7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.8.3.tgz#5e06654af5cd04b608915aada9b2a6788004464e" + integrity sha512-EqFhbo7IosdgPgZggHaNObkmO1kNUe3slaKu54d5OWvy+p9QIKOzK1GAEpAIsZtWVtPXUHSMcT4smvDrCfY4AA== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-proposal-decorators@7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.8.3.tgz#2156860ab65c5abf068c3f67042184041066543e" + integrity sha512-e3RvdvS4qPJVTe288DlXjwKflpfy1hr0j5dz5WpIYYeP7vQZg2WfAEIp8k5/Lwis/m5REXEteIz6rrcDtXXG7w== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-decorators" "^7.8.3" + "@babel/plugin-proposal-dynamic-import@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.7.4.tgz#dde64a7f127691758cbfed6cf70de0fa5879d52d" @@ -262,6 +582,14 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-dynamic-import" "^7.7.4" +"@babel/plugin-proposal-dynamic-import@^7.8.3": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.10.1.tgz#e36979dc1dc3b73f6d6816fc4951da2363488ef0" + integrity sha512-Cpc2yUVHTEGPlmiQzXj026kqwjEQAD9I4ZC16uzdbgWgitg/UHKHLffKNCQZ5+y8jpIZPJcKcwsr2HwPh+w3XA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.1" + "@babel/plugin-syntax-dynamic-import" "^7.8.0" + "@babel/plugin-proposal-json-strings@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.7.4.tgz#7700a6bfda771d8dc81973249eac416c6b4c697d" @@ -270,6 +598,46 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-json-strings" "^7.7.4" +"@babel/plugin-proposal-json-strings@^7.8.3": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.10.1.tgz#b1e691ee24c651b5a5e32213222b2379734aff09" + integrity sha512-m8r5BmV+ZLpWPtMY2mOKN7wre6HIO4gfIiV+eOmsnZABNenrt/kzYBwrh+KOfgumSWpnlGs5F70J8afYMSJMBg== + dependencies: + "@babel/helper-plugin-utils" "^7.10.1" + "@babel/plugin-syntax-json-strings" "^7.8.0" + +"@babel/plugin-proposal-nullish-coalescing-operator@7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.8.3.tgz#e4572253fdeed65cddeecfdab3f928afeb2fd5d2" + integrity sha512-TS9MlfzXpXKt6YYomudb/KU7nQI6/xnapG6in1uZxoxDghuSMZsPb6D2fyUwNYSAp4l1iR7QtFOjkqcRYcUsfw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" + +"@babel/plugin-proposal-nullish-coalescing-operator@^7.8.3": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.10.1.tgz#02dca21673842ff2fe763ac253777f235e9bbf78" + integrity sha512-56cI/uHYgL2C8HVuHOuvVowihhX0sxb3nnfVRzUeVHTWmRHTZrKuAh/OBIMggGU/S1g/1D2CRCXqP+3u7vX7iA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.1" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" + +"@babel/plugin-proposal-numeric-separator@7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.8.3.tgz#5d6769409699ec9b3b68684cd8116cedff93bad8" + integrity sha512-jWioO1s6R/R+wEHizfaScNsAx+xKgwTLNXSh7tTC4Usj3ItsPEhYkEpU4h+lpnBwq7NBVOJXfO6cRFYcX69JUQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.8.3" + +"@babel/plugin-proposal-numeric-separator@^7.8.3": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.10.1.tgz#a9a38bc34f78bdfd981e791c27c6fdcec478c123" + integrity sha512-jjfym4N9HtCiNfyyLAVD8WqPYeHUrw4ihxuAynWj6zzp2gf9Ey2f7ImhFm6ikB3CLf5Z/zmcJDri6B4+9j9RsA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.1" + "@babel/plugin-syntax-numeric-separator" "^7.10.1" + "@babel/plugin-proposal-object-rest-spread@^7.7.7": version "7.7.7" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.7.7.tgz#9f27075004ab99be08c5c1bd653a2985813cb370" @@ -278,6 +646,15 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-object-rest-spread" "^7.7.4" +"@babel/plugin-proposal-object-rest-spread@^7.9.0": + version "7.10.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.10.3.tgz#b8d0d22f70afa34ad84b7a200ff772f9b9fce474" + integrity sha512-ZZh5leCIlH9lni5bU/wB/UcjtcVLgR8gc+FAgW2OOY+m9h1II3ItTO1/cewNUcsIDZSYcSaz/rYVls+Fb0ExVQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.3" + "@babel/plugin-syntax-object-rest-spread" "^7.8.0" + "@babel/plugin-transform-parameters" "^7.10.1" + "@babel/plugin-proposal-optional-catch-binding@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.7.4.tgz#ec21e8aeb09ec6711bc0a39ca49520abee1de379" @@ -286,6 +663,38 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-optional-catch-binding" "^7.7.4" +"@babel/plugin-proposal-optional-catch-binding@^7.8.3": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.10.1.tgz#c9f86d99305f9fa531b568ff5ab8c964b8b223d2" + integrity sha512-VqExgeE62YBqI3ogkGoOJp1R6u12DFZjqwJhqtKc2o5m1YTUuUWnos7bZQFBhwkxIFpWYJ7uB75U7VAPPiKETA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.1" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" + +"@babel/plugin-proposal-optional-chaining@7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.9.0.tgz#31db16b154c39d6b8a645292472b98394c292a58" + integrity sha512-NDn5tu3tcv4W30jNhmc2hyD5c56G6cXx4TesJubhxrJeCvuuMpttxr0OnNCqbZGhFjLrg+NIhxxC+BK5F6yS3w== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.0" + +"@babel/plugin-proposal-optional-chaining@^7.9.0": + version "7.10.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.10.3.tgz#9a726f94622b653c0a3a7a59cdce94730f526f7c" + integrity sha512-yyG3n9dJ1vZ6v5sfmIlMMZ8azQoqx/5/nZTSWX1td6L1H1bsjzA8TInDChpafCZiJkeOFzp/PtrfigAQXxI1Ng== + dependencies: + "@babel/helper-plugin-utils" "^7.10.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.0" + +"@babel/plugin-proposal-unicode-property-regex@^7.4.4", "@babel/plugin-proposal-unicode-property-regex@^7.8.3": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.10.1.tgz#dc04feb25e2dd70c12b05d680190e138fa2c0c6f" + integrity sha512-JjfngYRvwmPwmnbRZyNiPFI8zxCZb8euzbCG/LxyKdeTb59tVciKo9GK9bi6JYKInk1H11Dq9j/zRqIH4KigfQ== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.1" + "@babel/plugin-proposal-unicode-property-regex@^7.7.7": version "7.7.7" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.7.7.tgz#433fa9dac64f953c12578b29633f456b68831c4e" @@ -301,6 +710,34 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-syntax-async-generators@^7.8.0", "@babel/plugin-syntax-async-generators@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-bigint@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" + integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-class-properties@^7.8.3": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.10.1.tgz#d5bc0645913df5b17ad7eda0fa2308330bde34c5" + integrity sha512-Gf2Yx/iRs1JREDtVZ56OrjjgFHCaldpTnuy9BHla10qyVT3YkIIGEtoDWhyop0ksu1GvNjHIoYRBqm3zoR1jyQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.1" + +"@babel/plugin-syntax-decorators@^7.8.3": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.10.1.tgz#16b869c4beafc9a442565147bda7ce0967bd4f13" + integrity sha512-a9OAbQhKOwSle1Vr0NJu/ISg1sPfdEkfRKWpgPuzhnWWzForou2gIeUIIwjAMHRekhhpJ7eulZlYs0H14Cbi+g== + dependencies: + "@babel/helper-plugin-utils" "^7.10.1" + "@babel/plugin-syntax-dynamic-import@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.7.4.tgz#29ca3b4415abfe4a5ec381e903862ad1a54c3aec" @@ -308,6 +745,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-syntax-dynamic-import@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" + integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + "@babel/plugin-syntax-flow@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.7.4.tgz#6d91b59e1a0e4c17f36af2e10dd64ef220919d7b" @@ -315,6 +759,20 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-syntax-flow@^7.8.3": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.10.1.tgz#cd4bbca62fb402babacb174f64f8734310d742f0" + integrity sha512-b3pWVncLBYoPP60UOTc7NMlbtsHQ6ITim78KQejNHK6WJ2mzV5kCcg4mIWpasAfJEgwVTibwo2e+FU7UEIKQUg== + dependencies: + "@babel/helper-plugin-utils" "^7.10.1" + +"@babel/plugin-syntax-import-meta@^7.8.3": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.1.tgz#3e59120ed8b3c2ccc5abb1cfc7aaa3ea01cd36b6" + integrity sha512-ypC4jwfIVF72og0dgvEcFRdOM2V9Qm1tu7RGmdZOlhsccyK0wisXmMObGuWEOd5jQ+K9wcIgSNftCpk2vkjUfQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.1" + "@babel/plugin-syntax-json-strings@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.7.4.tgz#86e63f7d2e22f9e27129ac4e83ea989a382e86cc" @@ -322,6 +780,20 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-syntax-json-strings@^7.8.0", "@babel/plugin-syntax-json-strings@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" + integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-jsx@^7.10.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.10.1.tgz#0ae371134a42b91d5418feb3c8c8d43e1565d2da" + integrity sha512-+OxyOArpVFXQeXKLO9o+r2I4dIoVoy6+Uu0vKELrlweDM3QJADZj+Z+5ERansZqIZBcLj42vHnDI8Rz9BnRIuQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.1" + "@babel/plugin-syntax-jsx@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.7.4.tgz#dab2b56a36fb6c3c222a1fbc71f7bf97f327a9ec" @@ -329,6 +801,27 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-syntax-logical-assignment-operators@^7.8.3": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.1.tgz#fffee77b4934ce77f3b427649ecdddbec1958550" + integrity sha512-XyHIFa9kdrgJS91CUH+ccPVTnJShr8nLGc5bG2IhGXv5p1Rd+8BleGE5yzIg2Nc1QZAdHDa0Qp4m6066OL96Iw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.1" + +"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.0", "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-numeric-separator@^7.10.1", "@babel/plugin-syntax-numeric-separator@^7.8.0", "@babel/plugin-syntax-numeric-separator@^7.8.3": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.1.tgz#25761ee7410bc8cf97327ba741ee94e4a61b7d99" + integrity sha512-uTd0OsHrpe3tH5gRPTxG8Voh99/WCU78vIm5NMRYPAqC8lR4vajt6KkCAknCHrx24vkPdd/05yfdGSB4EIY2mg== + dependencies: + "@babel/helper-plugin-utils" "^7.10.1" + "@babel/plugin-syntax-object-rest-spread@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.7.4.tgz#47cf220d19d6d0d7b154304701f468fc1cc6ff46" @@ -336,6 +829,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-syntax-object-rest-spread@^7.8.0", "@babel/plugin-syntax-object-rest-spread@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + "@babel/plugin-syntax-optional-catch-binding@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.7.4.tgz#a3e38f59f4b6233867b4a92dcb0ee05b2c334aa6" @@ -343,6 +843,20 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-syntax-optional-catch-binding@^7.8.0", "@babel/plugin-syntax-optional-catch-binding@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-chaining@^7.8.0", "@babel/plugin-syntax-optional-chaining@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + "@babel/plugin-syntax-top-level-await@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.7.4.tgz#bd7d8fa7b9fee793a36e4027fd6dd1aa32f946da" @@ -350,6 +864,20 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-syntax-top-level-await@^7.8.3": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.10.1.tgz#8b8733f8c57397b3eaa47ddba8841586dcaef362" + integrity sha512-hgA5RYkmZm8FTFT3yu2N9Bx7yVVOKYT6yEdXXo6j2JTm0wNxgqaGeQVaSHRjhfnQbX91DtjFB6McRFSlcJH3xQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.1" + +"@babel/plugin-syntax-typescript@^7.10.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.10.1.tgz#5e82bc27bb4202b93b949b029e699db536733810" + integrity sha512-X/d8glkrAtra7CaQGMiGs/OGa6XgUzqPcBXCIGFCpCqnfGlT0Wfbzo/B89xHhnInTaItPK8LALblVXcUOEh95Q== + dependencies: + "@babel/helper-plugin-utils" "^7.10.1" + "@babel/plugin-syntax-typescript@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.7.4.tgz#5d037ffa10f3b25a16f32570ebbe7a8c2efa304b" @@ -364,6 +892,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-arrow-functions@^7.8.3": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.10.1.tgz#cb5ee3a36f0863c06ead0b409b4cc43a889b295b" + integrity sha512-6AZHgFJKP3DJX0eCNJj01RpytUa3SOGawIxweHkNX2L6PYikOZmoh5B0d7hIHaIgveMjX990IAa/xK7jRTN8OA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.1" + "@babel/plugin-transform-async-to-generator@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.7.4.tgz#694cbeae6d613a34ef0292713fa42fb45c4470ba" @@ -373,6 +908,15 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-remap-async-to-generator" "^7.7.4" +"@babel/plugin-transform-async-to-generator@^7.8.3": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.10.1.tgz#e5153eb1a3e028f79194ed8a7a4bf55f862b2062" + integrity sha512-XCgYjJ8TY2slj6SReBUyamJn3k2JLUIiiR5b6t1mNCMSvv7yx+jJpaewakikp0uWFQSF7ChPPoe3dHmXLpISkg== + dependencies: + "@babel/helper-module-imports" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-remap-async-to-generator" "^7.10.1" + "@babel/plugin-transform-block-scoped-functions@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.7.4.tgz#d0d9d5c269c78eaea76227ace214b8d01e4d837b" @@ -380,6 +924,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-block-scoped-functions@^7.8.3": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.10.1.tgz#146856e756d54b20fff14b819456b3e01820b85d" + integrity sha512-B7K15Xp8lv0sOJrdVAoukKlxP9N59HS48V1J3U/JGj+Ad+MHq+am6xJVs85AgXrQn4LV8vaYFOB+pr/yIuzW8Q== + dependencies: + "@babel/helper-plugin-utils" "^7.10.1" + "@babel/plugin-transform-block-scoping@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.7.4.tgz#200aad0dcd6bb80372f94d9e628ea062c58bf224" @@ -388,6 +939,14 @@ "@babel/helper-plugin-utils" "^7.0.0" lodash "^4.17.13" +"@babel/plugin-transform-block-scoping@^7.8.3": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.10.1.tgz#47092d89ca345811451cd0dc5d91605982705d5e" + integrity sha512-8bpWG6TtF5akdhIm/uWTyjHqENpy13Fx8chg7pFH875aNLwX8JxIxqm08gmAT+Whe6AOmaTeLPe7dpLbXt+xUw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.1" + lodash "^4.17.13" + "@babel/plugin-transform-classes@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.7.4.tgz#c92c14be0a1399e15df72667067a8f510c9400ec" @@ -402,6 +961,20 @@ "@babel/helper-split-export-declaration" "^7.7.4" globals "^11.1.0" +"@babel/plugin-transform-classes@^7.9.0": + version "7.10.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.10.3.tgz#8d9a656bc3d01f3ff69e1fccb354b0f9d72ac544" + integrity sha512-irEX0ChJLaZVC7FvvRoSIxJlmk0IczFLcwaRXUArBKYHCHbOhe57aG8q3uw/fJsoSXvZhjRX960hyeAGlVBXZw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.1" + "@babel/helper-define-map" "^7.10.3" + "@babel/helper-function-name" "^7.10.3" + "@babel/helper-optimise-call-expression" "^7.10.3" + "@babel/helper-plugin-utils" "^7.10.3" + "@babel/helper-replace-supers" "^7.10.1" + "@babel/helper-split-export-declaration" "^7.10.1" + globals "^11.1.0" + "@babel/plugin-transform-computed-properties@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.7.4.tgz#e856c1628d3238ffe12d668eb42559f79a81910d" @@ -409,6 +982,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-computed-properties@^7.8.3": + version "7.10.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.10.3.tgz#d3aa6eef67cb967150f76faff20f0abbf553757b" + integrity sha512-GWzhaBOsdbjVFav96drOz7FzrcEW6AP5nax0gLIpstiFaI3LOb2tAg06TimaWU6YKOfUACK3FVrxPJ4GSc5TgA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.3" + "@babel/plugin-transform-destructuring@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.7.4.tgz#2b713729e5054a1135097b6a67da1b6fe8789267" @@ -416,6 +996,21 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-destructuring@^7.8.3": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.10.1.tgz#abd58e51337815ca3a22a336b85f62b998e71907" + integrity sha512-V/nUc4yGWG71OhaTH705pU8ZSdM6c1KmmLP8ys59oOYbT7RpMYAR3MsVOt6OHL0WzG7BlTU076va9fjJyYzJMA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.1" + +"@babel/plugin-transform-dotall-regex@^7.4.4", "@babel/plugin-transform-dotall-regex@^7.8.3": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.10.1.tgz#920b9fec2d78bb57ebb64a644d5c2ba67cc104ee" + integrity sha512-19VIMsD1dp02RvduFUmfzj8uknaO3uiHHF0s3E1OHnVsNj8oge8EQ5RzHRbJjGSetRnkEuBYO7TG1M5kKjGLOA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.1" + "@babel/plugin-transform-dotall-regex@^7.7.7": version "7.7.7" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.7.7.tgz#3e9713f1b69f339e87fa796b097d73ded16b937b" @@ -431,6 +1026,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-duplicate-keys@^7.8.3": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.10.1.tgz#c900a793beb096bc9d4d0a9d0cde19518ffc83b9" + integrity sha512-wIEpkX4QvX8Mo9W6XF3EdGttrIPZWozHfEaDTU0WJD/TDnXMvdDh30mzUl/9qWhnf7naicYartcEfUghTCSNpA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.1" + "@babel/plugin-transform-exponentiation-operator@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.7.4.tgz#dd30c0191e3a1ba19bcc7e389bdfddc0729d5db9" @@ -439,6 +1041,22 @@ "@babel/helper-builder-binary-assignment-operator-visitor" "^7.7.4" "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-exponentiation-operator@^7.8.3": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.10.1.tgz#279c3116756a60dd6e6f5e488ba7957db9c59eb3" + integrity sha512-lr/przdAbpEA2BUzRvjXdEDLrArGRRPwbaF9rvayuHRvdQ7lUTTkZnhZrJ4LE2jvgMRFF4f0YuPQ20vhiPYxtA== + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.1" + +"@babel/plugin-transform-flow-strip-types@7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.9.0.tgz#8a3538aa40434e000b8f44a3c5c9ac7229bd2392" + integrity sha512-7Qfg0lKQhEHs93FChxVLAvhBshOPQDtJUTVHr/ZwQNRccCm4O9D79r9tVSoV8iNwjP1YgfD+e/fgHcPkN1qEQg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-flow" "^7.8.3" + "@babel/plugin-transform-flow-strip-types@^7.0.0": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.7.4.tgz#cc73f85944782df1d77d80977bc097920a8bf31a" @@ -454,6 +1072,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-for-of@^7.9.0": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.10.1.tgz#ff01119784eb0ee32258e8646157ba2501fcfda5" + integrity sha512-US8KCuxfQcn0LwSCMWMma8M2R5mAjJGsmoCBVwlMygvmDUMkTCykc84IqN1M7t+agSfOmLYTInLCHJM+RUoz+w== + dependencies: + "@babel/helper-plugin-utils" "^7.10.1" + "@babel/plugin-transform-function-name@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.7.4.tgz#75a6d3303d50db638ff8b5385d12451c865025b1" @@ -462,6 +1087,14 @@ "@babel/helper-function-name" "^7.7.4" "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-function-name@^7.8.3": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.10.1.tgz#4ed46fd6e1d8fde2a2ec7b03c66d853d2c92427d" + integrity sha512-//bsKsKFBJfGd65qSNNh1exBy5Y9gD9ZN+DvrJ8f7HXr4avE5POW6zB7Rj6VnqHV33+0vXWUwJT0wSHubiAQkw== + dependencies: + "@babel/helper-function-name" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.1" + "@babel/plugin-transform-literals@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.7.4.tgz#27fe87d2b5017a2a5a34d1c41a6b9f6a6262643e" @@ -469,6 +1102,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-literals@^7.8.3": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.10.1.tgz#5794f8da82846b22e4e6631ea1658bce708eb46a" + integrity sha512-qi0+5qgevz1NHLZroObRm5A+8JJtibb7vdcPQF1KQE12+Y/xxl8coJ+TpPW9iRq+Mhw/NKLjm+5SHtAHCC7lAw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.1" + "@babel/plugin-transform-member-expression-literals@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.7.4.tgz#aee127f2f3339fc34ce5e3055d7ffbf7aa26f19a" @@ -476,6 +1116,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-member-expression-literals@^7.8.3": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.10.1.tgz#90347cba31bca6f394b3f7bd95d2bbfd9fce2f39" + integrity sha512-UmaWhDokOFT2GcgU6MkHC11i0NQcL63iqeufXWfRy6pUOGYeCGEKhvfFO6Vz70UfYJYHwveg62GS83Rvpxn+NA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.1" + "@babel/plugin-transform-modules-amd@^7.7.5": version "7.7.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.7.5.tgz#39e0fb717224b59475b306402bb8eedab01e729c" @@ -485,6 +1132,15 @@ "@babel/helper-plugin-utils" "^7.0.0" babel-plugin-dynamic-import-node "^2.3.0" +"@babel/plugin-transform-modules-amd@^7.9.0": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.10.1.tgz#65950e8e05797ebd2fe532b96e19fc5482a1d52a" + integrity sha512-31+hnWSFRI4/ACFr1qkboBbrTxoBIzj7qA69qlq8HY8p7+YCzkCT6/TvQ1a4B0z27VeWtAeJd6pr5G04dc1iHw== + dependencies: + "@babel/helper-module-transforms" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.1" + babel-plugin-dynamic-import-node "^2.3.3" + "@babel/plugin-transform-modules-commonjs@^7.0.0", "@babel/plugin-transform-modules-commonjs@^7.7.5": version "7.7.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.7.5.tgz#1d27f5eb0bcf7543e774950e5b2fa782e637b345" @@ -495,6 +1151,16 @@ "@babel/helper-simple-access" "^7.7.4" babel-plugin-dynamic-import-node "^2.3.0" +"@babel/plugin-transform-modules-commonjs@^7.9.0": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.10.1.tgz#d5ff4b4413ed97ffded99961056e1fb980fb9301" + integrity sha512-AQG4fc3KOah0vdITwt7Gi6hD9BtQP/8bhem7OjbaMoRNCH5Djx42O2vYMfau7QnAzQCa+RJnhJBmFFMGpQEzrg== + dependencies: + "@babel/helper-module-transforms" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-simple-access" "^7.10.1" + babel-plugin-dynamic-import-node "^2.3.3" + "@babel/plugin-transform-modules-systemjs@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.7.4.tgz#cd98152339d3e763dfe838b7d4273edaf520bb30" @@ -504,6 +1170,16 @@ "@babel/helper-plugin-utils" "^7.0.0" babel-plugin-dynamic-import-node "^2.3.0" +"@babel/plugin-transform-modules-systemjs@^7.9.0": + version "7.10.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.10.3.tgz#004ae727b122b7b146b150d50cba5ffbff4ac56b" + integrity sha512-GWXWQMmE1GH4ALc7YXW56BTh/AlzvDWhUNn9ArFF0+Cz5G8esYlVbXfdyHa1xaD1j+GnBoCeoQNlwtZTVdiG/A== + dependencies: + "@babel/helper-hoist-variables" "^7.10.3" + "@babel/helper-module-transforms" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.3" + babel-plugin-dynamic-import-node "^2.3.3" + "@babel/plugin-transform-modules-umd@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.7.4.tgz#1027c355a118de0aae9fee00ad7813c584d9061f" @@ -512,6 +1188,14 @@ "@babel/helper-module-transforms" "^7.7.4" "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-modules-umd@^7.9.0": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.10.1.tgz#ea080911ffc6eb21840a5197a39ede4ee67b1595" + integrity sha512-EIuiRNMd6GB6ulcYlETnYYfgv4AxqrswghmBRQbWLHZxN4s7mupxzglnHqk9ZiUpDI4eRWewedJJNj67PWOXKA== + dependencies: + "@babel/helper-module-transforms" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.1" + "@babel/plugin-transform-named-capturing-groups-regex@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.7.4.tgz#fb3bcc4ee4198e7385805007373d6b6f42c98220" @@ -519,6 +1203,13 @@ dependencies: "@babel/helper-create-regexp-features-plugin" "^7.7.4" +"@babel/plugin-transform-named-capturing-groups-regex@^7.8.3": + version "7.10.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.10.3.tgz#a4f8444d1c5a46f35834a410285f2c901c007ca6" + integrity sha512-I3EH+RMFyVi8Iy/LekQm948Z4Lz4yKT7rK+vuCAeRm0kTa6Z5W7xuhRxDNJv0FPya/her6AUgrDITb70YHtTvA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.8.3" + "@babel/plugin-transform-new-target@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.7.4.tgz#4a0753d2d60639437be07b592a9e58ee00720167" @@ -526,6 +1217,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-new-target@^7.8.3": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.10.1.tgz#6ee41a5e648da7632e22b6fb54012e87f612f324" + integrity sha512-MBlzPc1nJvbmO9rPr1fQwXOM2iGut+JC92ku6PbiJMMK7SnQc1rytgpopveE3Evn47gzvGYeCdgfCDbZo0ecUw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.1" + "@babel/plugin-transform-object-super@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.7.4.tgz#48488937a2d586c0148451bf51af9d7dda567262" @@ -534,6 +1232,22 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-replace-supers" "^7.7.4" +"@babel/plugin-transform-object-super@^7.8.3": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.10.1.tgz#2e3016b0adbf262983bf0d5121d676a5ed9c4fde" + integrity sha512-WnnStUDN5GL+wGQrJylrnnVlFhFmeArINIR9gjhSeYyvroGhBrSAXYg/RHsnfzmsa+onJrTJrEClPzgNmmQ4Gw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-replace-supers" "^7.10.1" + +"@babel/plugin-transform-parameters@^7.10.1", "@babel/plugin-transform-parameters@^7.8.7": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.10.1.tgz#b25938a3c5fae0354144a720b07b32766f683ddd" + integrity sha512-tJ1T0n6g4dXMsL45YsSzzSDZCxiHXAQp/qHrucOq5gEHncTA3xDxnd5+sZcoQp+N1ZbieAaB8r/VUCG0gqseOg== + dependencies: + "@babel/helper-get-function-arity" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.1" + "@babel/plugin-transform-parameters@^7.7.7": version "7.7.7" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.7.7.tgz#7a884b2460164dc5f194f668332736584c760007" @@ -550,6 +1264,52 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-property-literals@^7.8.3": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.10.1.tgz#cffc7315219230ed81dc53e4625bf86815b6050d" + integrity sha512-Kr6+mgag8auNrgEpbfIWzdXYOvqDHZOF0+Bx2xh4H2EDNwcbRb9lY6nkZg8oSjsX+DH9Ebxm9hOqtKW+gRDeNA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.1" + +"@babel/plugin-transform-react-display-name@7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.8.3.tgz#70ded987c91609f78353dd76d2fb2a0bb991e8e5" + integrity sha512-3Jy/PCw8Fe6uBKtEgz3M82ljt+lTg+xJaM4og+eyu83qLT87ZUSckn0wy7r31jflURWLO83TW6Ylf7lyXj3m5A== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-react-display-name@^7.8.3": + version "7.10.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.10.3.tgz#e3c246e1b4f3e52cc7633e237ad9194c0ec482e7" + integrity sha512-dOV44bnSW5KZ6kYF6xSHBth7TFiHHZReYXH/JH3XnFNV+soEL1F5d8JT7AJ3ZBncd19Qul7SN4YpBnyWOnQ8KA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.3" + +"@babel/plugin-transform-react-jsx-development@^7.9.0": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.10.1.tgz#1ac6300d8b28ef381ee48e6fec430cc38047b7f3" + integrity sha512-XwDy/FFoCfw9wGFtdn5Z+dHh6HXKHkC6DwKNWpN74VWinUagZfDcEJc3Y8Dn5B3WMVnAllX8Kviaw7MtC5Epwg== + dependencies: + "@babel/helper-builder-react-jsx-experimental" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.1" + "@babel/plugin-syntax-jsx" "^7.10.1" + +"@babel/plugin-transform-react-jsx-self@^7.9.0": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.10.1.tgz#22143e14388d72eb88649606bb9e46f421bc3821" + integrity sha512-4p+RBw9d1qV4S749J42ZooeQaBomFPrSxa9JONLHJ1TxCBo3TzJ79vtmG2S2erUT8PDDrPdw4ZbXGr2/1+dILA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.1" + "@babel/plugin-syntax-jsx" "^7.10.1" + +"@babel/plugin-transform-react-jsx-source@^7.9.0": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.10.1.tgz#30db3d4ee3cdebbb26a82a9703673714777a4273" + integrity sha512-neAbaKkoiL+LXYbGDvh6PjPG+YeA67OsZlE78u50xbWh2L1/C81uHiNP5d1fw+uqUIoiNdCC8ZB+G4Zh3hShJA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.1" + "@babel/plugin-syntax-jsx" "^7.10.1" + "@babel/plugin-transform-react-jsx@^7.0.0": version "7.7.7" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.7.7.tgz#5cbaa7445b4a09f774029f3cc7bb448ff3122a5d" @@ -559,6 +1319,16 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-jsx" "^7.7.4" +"@babel/plugin-transform-react-jsx@^7.9.1": + version "7.10.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.10.3.tgz#c07ad86b7c159287c89b643f201f59536231048e" + integrity sha512-Y21E3rZmWICRJnvbGVmDLDZ8HfNDIwjGF3DXYHx1le0v0mIHCs0Gv5SavyW5Z/jgAHLaAoJPiwt+Dr7/zZKcOQ== + dependencies: + "@babel/helper-builder-react-jsx" "^7.10.3" + "@babel/helper-builder-react-jsx-experimental" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.3" + "@babel/plugin-syntax-jsx" "^7.10.1" + "@babel/plugin-transform-regenerator@^7.7.5": version "7.7.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.7.5.tgz#3a8757ee1a2780f390e89f246065ecf59c26fce9" @@ -566,6 +1336,13 @@ dependencies: regenerator-transform "^0.14.0" +"@babel/plugin-transform-regenerator@^7.8.7": + version "7.10.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.10.3.tgz#6ec680f140a5ceefd291c221cb7131f6d7e8cb6d" + integrity sha512-H5kNeW0u8mbk0qa1jVIVTeJJL6/TJ81ltD4oyPx0P499DhMJrTmmIFCmJ3QloGpQG8K9symccB7S7SJpCKLwtw== + dependencies: + regenerator-transform "^0.14.2" + "@babel/plugin-transform-reserved-words@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.7.4.tgz#6a7cf123ad175bb5c69aec8f6f0770387ed3f1eb" @@ -573,6 +1350,23 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-reserved-words@^7.8.3": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.10.1.tgz#0fc1027312b4d1c3276a57890c8ae3bcc0b64a86" + integrity sha512-qN1OMoE2nuqSPmpTqEM7OvJ1FkMEV+BjVeZZm9V9mq/x1JLKQ4pcv8riZJMNN3u2AUGl0ouOMjRr2siecvHqUQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.1" + +"@babel/plugin-transform-runtime@7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.9.0.tgz#45468c0ae74cc13204e1d3b1f4ce6ee83258af0b" + integrity sha512-pUu9VSf3kI1OqbWINQ7MaugnitRss1z533436waNXp+0N3ur3zfut37sXiQMxkuCF4VUjwZucen/quskCh7NHw== + dependencies: + "@babel/helper-module-imports" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + resolve "^1.8.1" + semver "^5.5.1" + "@babel/plugin-transform-shorthand-properties@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.7.4.tgz#74a0a9b2f6d67a684c6fbfd5f0458eb7ba99891e" @@ -580,6 +1374,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-shorthand-properties@^7.8.3": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.10.1.tgz#e8b54f238a1ccbae482c4dce946180ae7b3143f3" + integrity sha512-AR0E/lZMfLstScFwztApGeyTHJ5u3JUKMjneqRItWeEqDdHWZwAOKycvQNCasCK/3r5YXsuNG25funcJDu7Y2g== + dependencies: + "@babel/helper-plugin-utils" "^7.10.1" + "@babel/plugin-transform-spread@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.7.4.tgz#aa673b356fe6b7e70d69b6e33a17fef641008578" @@ -587,6 +1388,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-spread@^7.8.3": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.10.1.tgz#0c6d618a0c4461a274418460a28c9ccf5239a7c8" + integrity sha512-8wTPym6edIrClW8FI2IoaePB91ETOtg36dOkj3bYcNe7aDMN2FXEoUa+WrmPc4xa1u2PQK46fUX2aCb+zo9rfw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.1" + "@babel/plugin-transform-sticky-regex@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.7.4.tgz#ffb68c05090c30732076b1285dc1401b404a123c" @@ -595,6 +1403,14 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-regex" "^7.0.0" +"@babel/plugin-transform-sticky-regex@^7.8.3": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.10.1.tgz#90fc89b7526228bed9842cff3588270a7a393b00" + integrity sha512-j17ojftKjrL7ufX8ajKvwRilwqTok4q+BjkknmQw9VNHnItTyMP5anPFzxFJdCQs7clLcWpCV3ma+6qZWLnGMA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-regex" "^7.10.1" + "@babel/plugin-transform-template-literals@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.7.4.tgz#1eb6411736dd3fe87dbd20cc6668e5121c17d604" @@ -603,6 +1419,14 @@ "@babel/helper-annotate-as-pure" "^7.7.4" "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-template-literals@^7.8.3": + version "7.10.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.10.3.tgz#69d39b3d44b31e7b4864173322565894ce939b25" + integrity sha512-yaBn9OpxQra/bk0/CaA4wr41O0/Whkg6nqjqApcinxM7pro51ojhX6fv1pimAnVjVfDy14K0ULoRL70CA9jWWA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.3" + "@babel/plugin-transform-typeof-symbol@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.7.4.tgz#3174626214f2d6de322882e498a38e8371b2140e" @@ -610,6 +1434,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-typeof-symbol@^7.8.4": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.10.1.tgz#60c0239b69965d166b80a84de7315c1bc7e0bb0e" + integrity sha512-qX8KZcmbvA23zDi+lk9s6hC1FM7jgLHYIjuLgULgc8QtYnmB3tAVIYkNoKRQ75qWBeyzcoMoK8ZQmogGtC/w0g== + dependencies: + "@babel/helper-plugin-utils" "^7.10.1" + "@babel/plugin-transform-typescript@^7.4.5": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.7.4.tgz#2974fd05f4e85c695acaf497f432342de9fc0636" @@ -619,6 +1450,15 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-typescript" "^7.7.4" +"@babel/plugin-transform-typescript@^7.9.0": + version "7.10.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.10.3.tgz#b3b35fb34ef0bd628b4b8329b0e5f985369201d4" + integrity sha512-qU9Lu7oQyh3PGMQncNjQm8RWkzw6LqsWZQlZPQMgrGt6s3YiBIaQ+3CQV/FA/icGS5XlSWZGwo/l8ErTyelS0Q== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.10.3" + "@babel/helper-plugin-utils" "^7.10.3" + "@babel/plugin-syntax-typescript" "^7.10.1" + "@babel/plugin-transform-unicode-regex@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.7.4.tgz#a3c0f65b117c4c81c5b6484f2a5e7b95346b83ae" @@ -627,6 +1467,80 @@ "@babel/helper-create-regexp-features-plugin" "^7.7.4" "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-unicode-regex@^7.8.3": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.10.1.tgz#6b58f2aea7b68df37ac5025d9c88752443a6b43f" + integrity sha512-Y/2a2W299k0VIUdbqYm9X2qS6fE0CUBhhiPpimK6byy7OJ/kORLlIX+J6UrjgNu5awvs62k+6RSslxhcvVw2Tw== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.1" + +"@babel/preset-env@7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.9.0.tgz#a5fc42480e950ae8f5d9f8f2bbc03f52722df3a8" + integrity sha512-712DeRXT6dyKAM/FMbQTV/FvRCms2hPCx+3weRjZ8iQVQWZejWWk1wwG6ViWMyqb/ouBbGOl5b6aCk0+j1NmsQ== + dependencies: + "@babel/compat-data" "^7.9.0" + "@babel/helper-compilation-targets" "^7.8.7" + "@babel/helper-module-imports" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-proposal-async-generator-functions" "^7.8.3" + "@babel/plugin-proposal-dynamic-import" "^7.8.3" + "@babel/plugin-proposal-json-strings" "^7.8.3" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-proposal-numeric-separator" "^7.8.3" + "@babel/plugin-proposal-object-rest-spread" "^7.9.0" + "@babel/plugin-proposal-optional-catch-binding" "^7.8.3" + "@babel/plugin-proposal-optional-chaining" "^7.9.0" + "@babel/plugin-proposal-unicode-property-regex" "^7.8.3" + "@babel/plugin-syntax-async-generators" "^7.8.0" + "@babel/plugin-syntax-dynamic-import" "^7.8.0" + "@babel/plugin-syntax-json-strings" "^7.8.0" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" + "@babel/plugin-syntax-numeric-separator" "^7.8.0" + "@babel/plugin-syntax-object-rest-spread" "^7.8.0" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" + "@babel/plugin-syntax-optional-chaining" "^7.8.0" + "@babel/plugin-syntax-top-level-await" "^7.8.3" + "@babel/plugin-transform-arrow-functions" "^7.8.3" + "@babel/plugin-transform-async-to-generator" "^7.8.3" + "@babel/plugin-transform-block-scoped-functions" "^7.8.3" + "@babel/plugin-transform-block-scoping" "^7.8.3" + "@babel/plugin-transform-classes" "^7.9.0" + "@babel/plugin-transform-computed-properties" "^7.8.3" + "@babel/plugin-transform-destructuring" "^7.8.3" + "@babel/plugin-transform-dotall-regex" "^7.8.3" + "@babel/plugin-transform-duplicate-keys" "^7.8.3" + "@babel/plugin-transform-exponentiation-operator" "^7.8.3" + "@babel/plugin-transform-for-of" "^7.9.0" + "@babel/plugin-transform-function-name" "^7.8.3" + "@babel/plugin-transform-literals" "^7.8.3" + "@babel/plugin-transform-member-expression-literals" "^7.8.3" + "@babel/plugin-transform-modules-amd" "^7.9.0" + "@babel/plugin-transform-modules-commonjs" "^7.9.0" + "@babel/plugin-transform-modules-systemjs" "^7.9.0" + "@babel/plugin-transform-modules-umd" "^7.9.0" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.8.3" + "@babel/plugin-transform-new-target" "^7.8.3" + "@babel/plugin-transform-object-super" "^7.8.3" + "@babel/plugin-transform-parameters" "^7.8.7" + "@babel/plugin-transform-property-literals" "^7.8.3" + "@babel/plugin-transform-regenerator" "^7.8.7" + "@babel/plugin-transform-reserved-words" "^7.8.3" + "@babel/plugin-transform-shorthand-properties" "^7.8.3" + "@babel/plugin-transform-spread" "^7.8.3" + "@babel/plugin-transform-sticky-regex" "^7.8.3" + "@babel/plugin-transform-template-literals" "^7.8.3" + "@babel/plugin-transform-typeof-symbol" "^7.8.4" + "@babel/plugin-transform-unicode-regex" "^7.8.3" + "@babel/preset-modules" "^0.1.3" + "@babel/types" "^7.9.0" + browserslist "^4.9.1" + core-js-compat "^3.6.2" + invariant "^2.2.2" + levenary "^1.1.1" + semver "^5.5.0" + "@babel/preset-env@^7.0.0": version "7.7.7" resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.7.7.tgz#c294167b91e53e7e36d820e943ece8d0c7fe46ac" @@ -684,6 +1598,59 @@ js-levenshtein "^1.1.3" semver "^5.5.0" +"@babel/preset-modules@^0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.3.tgz#13242b53b5ef8c883c3cf7dddd55b36ce80fbc72" + integrity sha512-Ra3JXOHBq2xd56xSF7lMKXdjBn3T772Y1Wet3yWnkDly9zHvJki029tAFzvAAK5cf4YV3yoxuP61crYRol6SVg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" + "@babel/plugin-transform-dotall-regex" "^7.4.4" + "@babel/types" "^7.4.4" + esutils "^2.0.2" + +"@babel/preset-react@7.9.1": + version "7.9.1" + resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.9.1.tgz#b346403c36d58c3bb544148272a0cefd9c28677a" + integrity sha512-aJBYF23MPj0RNdp/4bHnAP0NVqqZRr9kl0NAOP4nJCex6OYVio59+dnQzsAWFuogdLyeaKA1hmfUIVZkY5J+TQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-transform-react-display-name" "^7.8.3" + "@babel/plugin-transform-react-jsx" "^7.9.1" + "@babel/plugin-transform-react-jsx-development" "^7.9.0" + "@babel/plugin-transform-react-jsx-self" "^7.9.0" + "@babel/plugin-transform-react-jsx-source" "^7.9.0" + +"@babel/preset-typescript@7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.9.0.tgz#87705a72b1f0d59df21c179f7c3d2ef4b16ce192" + integrity sha512-S4cueFnGrIbvYJgwsVFKdvOmpiL0XGw9MFW9D0vgRys5g36PBhZRL8NX8Gr2akz8XRtzq6HuDXPD/1nniagNUg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-transform-typescript" "^7.9.0" + +"@babel/runtime-corejs3@^7.10.2": + version "7.10.3" + resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.10.3.tgz#931ed6941d3954924a7aa967ee440e60c507b91a" + integrity sha512-HA7RPj5xvJxQl429r5Cxr2trJwOfPjKiqhCXcdQPSqO2G0RHPZpXu4fkYmBaTKCp2c/jRaMK9GB/lN+7zvvFPw== + dependencies: + core-js-pure "^3.0.0" + regenerator-runtime "^0.13.4" + +"@babel/runtime@7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.9.0.tgz#337eda67401f5b066a6f205a3113d4ac18ba495b" + integrity sha512-cTIudHnzuWLS56ik4DnRnqqNf8MkdUzV4iFFI1h7Jo9xvrpQROYaAnaSd2mHLQAzzZAPfATynX5ord6YlNYNMA== + dependencies: + regenerator-runtime "^0.13.4" + +"@babel/runtime@^7.10.2", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2": + version "7.10.3" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.10.3.tgz#670d002655a7c366540c67f6fd3342cd09500364" + integrity sha512-RzGO0RLSdokm9Ipe/YD+7ww8X2Ro79qiXZF3HU9ljrM+qnJmH1Vqth+hbiQZy761LnMJTMitHDuKVYTk3k4dLw== + dependencies: + regenerator-runtime "^0.13.4" + "@babel/template@^7.0.0", "@babel/template@^7.2.2", "@babel/template@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.7.4.tgz#428a7d9eecffe27deac0a98e23bf8e3675d2a77b" @@ -693,6 +1660,15 @@ "@babel/parser" "^7.7.4" "@babel/types" "^7.7.4" +"@babel/template@^7.10.1", "@babel/template@^7.10.3", "@babel/template@^7.3.3", "@babel/template@^7.8.6": + version "7.10.3" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.3.tgz#4d13bc8e30bf95b0ce9d175d30306f42a2c9a7b8" + integrity sha512-5BjI4gdtD+9fHZUsaxPHPNpwa+xRkDO7c7JbhYn2afvrkDu5SfAAbi9AIMXw2xEhO/BR35TqiW97IqNvCo/GqA== + dependencies: + "@babel/code-frame" "^7.10.3" + "@babel/parser" "^7.10.3" + "@babel/types" "^7.10.3" + "@babel/traverse@^7.0.0", "@babel/traverse@^7.2.3", "@babel/traverse@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.7.4.tgz#9c1e7c60fb679fe4fcfaa42500833333c2058558" @@ -708,6 +1684,21 @@ globals "^11.1.0" lodash "^4.17.13" +"@babel/traverse@^7.1.0", "@babel/traverse@^7.10.1", "@babel/traverse@^7.10.3", "@babel/traverse@^7.9.0": + version "7.10.3" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.10.3.tgz#0b01731794aa7b77b214bcd96661f18281155d7e" + integrity sha512-qO6623eBFhuPm0TmmrUFMT1FulCmsSeJuVGhiLodk2raUDFhhTECLd9E9jC4LBIWziqt4wgF6KuXE4d+Jz9yug== + dependencies: + "@babel/code-frame" "^7.10.3" + "@babel/generator" "^7.10.3" + "@babel/helper-function-name" "^7.10.3" + "@babel/helper-split-export-declaration" "^7.10.1" + "@babel/parser" "^7.10.3" + "@babel/types" "^7.10.3" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.13" + "@babel/types@^7.0.0", "@babel/types@^7.3.3", "@babel/types@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.7.4.tgz#516570d539e44ddf308c07569c258ff94fde9193" @@ -717,11 +1708,225 @@ lodash "^4.17.13" to-fast-properties "^2.0.0" +"@babel/types@^7.10.1", "@babel/types@^7.10.3", "@babel/types@^7.3.0", "@babel/types@^7.4.4", "@babel/types@^7.9.0": + version "7.10.3" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.10.3.tgz#6535e3b79fea86a6b09e012ea8528f935099de8e" + integrity sha512-nZxaJhBXBQ8HVoIcGsf9qWep3Oh3jCENK54V4mRF7qaJabVsAYdbTtmSD8WmAp1R6ytPiu5apMwSXyxB1WlaBA== + dependencies: + "@babel/helper-validator-identifier" "^7.10.3" + lodash "^4.17.13" + to-fast-properties "^2.0.0" + +"@bcoe/v8-coverage@^0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" + integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== + +"@cnakazawa/watch@^1.0.3": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.4.tgz#f864ae85004d0fcab6f50be9141c4da368d1656a" + integrity sha512-v9kIhKwjeZThiWrLmj0y17CWoyddASLj9O2yvbZkbvw/N3rWOYy9zkV66ursAoVr0mV15bL8g0c4QZUE6cdDoQ== + dependencies: + exec-sh "^0.3.2" + minimist "^1.2.0" + "@iarna/toml@^2.2.0": version "2.2.3" resolved "https://registry.yarnpkg.com/@iarna/toml/-/toml-2.2.3.tgz#f060bf6eaafae4d56a7dac618980838b0696e2ab" integrity sha512-FmuxfCuolpLl0AnQ2NHSzoUKWEJDFl63qXjzdoWBVyFCXzMGm1spBzk7LeHNoVCiWCF7mRVms9e6jEV9+MoPbg== +"@istanbuljs/load-nyc-config@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" + integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== + dependencies: + camelcase "^5.3.1" + find-up "^4.1.0" + get-package-type "^0.1.0" + js-yaml "^3.13.1" + resolve-from "^5.0.0" + +"@istanbuljs/schema@^0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd" + integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw== + +"@jest/console@^26.0.1": + version "26.0.1" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-26.0.1.tgz#62b3b2fa8990f3cbffbef695c42ae9ddbc8f4b39" + integrity sha512-9t1KUe/93coV1rBSxMmBAOIK3/HVpwxArCA1CxskKyRiv6o8J70V8C/V3OJminVCTa2M0hQI9AWRd5wxu2dAHw== + dependencies: + "@jest/types" "^26.0.1" + chalk "^4.0.0" + jest-message-util "^26.0.1" + jest-util "^26.0.1" + slash "^3.0.0" + +"@jest/core@^26.0.1": + version "26.0.1" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-26.0.1.tgz#aa538d52497dfab56735efb00e506be83d841fae" + integrity sha512-Xq3eqYnxsG9SjDC+WLeIgf7/8KU6rddBxH+SCt18gEpOhAGYC/Mq+YbtlNcIdwjnnT+wDseXSbU0e5X84Y4jTQ== + dependencies: + "@jest/console" "^26.0.1" + "@jest/reporters" "^26.0.1" + "@jest/test-result" "^26.0.1" + "@jest/transform" "^26.0.1" + "@jest/types" "^26.0.1" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + exit "^0.1.2" + graceful-fs "^4.2.4" + jest-changed-files "^26.0.1" + jest-config "^26.0.1" + jest-haste-map "^26.0.1" + jest-message-util "^26.0.1" + jest-regex-util "^26.0.0" + jest-resolve "^26.0.1" + jest-resolve-dependencies "^26.0.1" + jest-runner "^26.0.1" + jest-runtime "^26.0.1" + jest-snapshot "^26.0.1" + jest-util "^26.0.1" + jest-validate "^26.0.1" + jest-watcher "^26.0.1" + micromatch "^4.0.2" + p-each-series "^2.1.0" + rimraf "^3.0.0" + slash "^3.0.0" + strip-ansi "^6.0.0" + +"@jest/environment@^26.0.1": + version "26.0.1" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-26.0.1.tgz#82f519bba71959be9b483675ee89de8c8f72a5c8" + integrity sha512-xBDxPe8/nx251u0VJ2dFAFz2H23Y98qdIaNwnMK6dFQr05jc+Ne/2np73lOAx+5mSBO/yuQldRrQOf6hP1h92g== + dependencies: + "@jest/fake-timers" "^26.0.1" + "@jest/types" "^26.0.1" + jest-mock "^26.0.1" + +"@jest/fake-timers@^26.0.1": + version "26.0.1" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-26.0.1.tgz#f7aeff13b9f387e9d0cac9a8de3bba538d19d796" + integrity sha512-Oj/kCBnTKhm7CR+OJSjZty6N1bRDr9pgiYQr4wY221azLz5PHi08x/U+9+QpceAYOWheauLP8MhtSVFrqXQfhg== + dependencies: + "@jest/types" "^26.0.1" + "@sinonjs/fake-timers" "^6.0.1" + jest-message-util "^26.0.1" + jest-mock "^26.0.1" + jest-util "^26.0.1" + +"@jest/globals@^26.0.1": + version "26.0.1" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-26.0.1.tgz#3f67b508a7ce62b6e6efc536f3d18ec9deb19a9c" + integrity sha512-iuucxOYB7BRCvT+TYBzUqUNuxFX1hqaR6G6IcGgEqkJ5x4htNKo1r7jk1ji9Zj8ZMiMw0oB5NaA7k5Tx6MVssA== + dependencies: + "@jest/environment" "^26.0.1" + "@jest/types" "^26.0.1" + expect "^26.0.1" + +"@jest/reporters@^26.0.1": + version "26.0.1" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-26.0.1.tgz#14ae00e7a93e498cec35b0c00ab21c375d9b078f" + integrity sha512-NWWy9KwRtE1iyG/m7huiFVF9YsYv/e+mbflKRV84WDoJfBqUrNRyDbL/vFxQcYLl8IRqI4P3MgPn386x76Gf2g== + dependencies: + "@bcoe/v8-coverage" "^0.2.3" + "@jest/console" "^26.0.1" + "@jest/test-result" "^26.0.1" + "@jest/transform" "^26.0.1" + "@jest/types" "^26.0.1" + chalk "^4.0.0" + collect-v8-coverage "^1.0.0" + exit "^0.1.2" + glob "^7.1.2" + graceful-fs "^4.2.4" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-instrument "^4.0.0" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^4.0.0" + istanbul-reports "^3.0.2" + jest-haste-map "^26.0.1" + jest-resolve "^26.0.1" + jest-util "^26.0.1" + jest-worker "^26.0.0" + slash "^3.0.0" + source-map "^0.6.0" + string-length "^4.0.1" + terminal-link "^2.0.0" + v8-to-istanbul "^4.1.3" + optionalDependencies: + node-notifier "^7.0.0" + +"@jest/source-map@^26.0.0": + version "26.0.0" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-26.0.0.tgz#fd7706484a7d3faf7792ae29783933bbf48a4749" + integrity sha512-S2Z+Aj/7KOSU2TfW0dyzBze7xr95bkm5YXNUqqCek+HE0VbNNSNzrRwfIi5lf7wvzDTSS0/ib8XQ1krFNyYgbQ== + dependencies: + callsites "^3.0.0" + graceful-fs "^4.2.4" + source-map "^0.6.0" + +"@jest/test-result@^26.0.1": + version "26.0.1" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-26.0.1.tgz#1ffdc1ba4bc289919e54b9414b74c9c2f7b2b718" + integrity sha512-oKwHvOI73ICSYRPe8WwyYPTtiuOAkLSbY8/MfWF3qDEd/sa8EDyZzin3BaXTqufir/O/Gzea4E8Zl14XU4Mlyg== + dependencies: + "@jest/console" "^26.0.1" + "@jest/types" "^26.0.1" + "@types/istanbul-lib-coverage" "^2.0.0" + collect-v8-coverage "^1.0.0" + +"@jest/test-sequencer@^26.0.1": + version "26.0.1" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-26.0.1.tgz#b0563424728f3fe9e75d1442b9ae4c11da73f090" + integrity sha512-ssga8XlwfP8YjbDcmVhwNlrmblddMfgUeAkWIXts1V22equp2GMIHxm7cyeD5Q/B0ZgKPK/tngt45sH99yLLGg== + dependencies: + "@jest/test-result" "^26.0.1" + graceful-fs "^4.2.4" + jest-haste-map "^26.0.1" + jest-runner "^26.0.1" + jest-runtime "^26.0.1" + +"@jest/transform@^26.0.1": + version "26.0.1" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-26.0.1.tgz#0e3ecbb34a11cd4b2080ed0a9c4856cf0ceb0639" + integrity sha512-pPRkVkAQ91drKGbzCfDOoHN838+FSbYaEAvBXvKuWeeRRUD8FjwXkqfUNUZL6Ke48aA/1cqq/Ni7kVMCoqagWA== + dependencies: + "@babel/core" "^7.1.0" + "@jest/types" "^26.0.1" + babel-plugin-istanbul "^6.0.0" + chalk "^4.0.0" + convert-source-map "^1.4.0" + fast-json-stable-stringify "^2.0.0" + graceful-fs "^4.2.4" + jest-haste-map "^26.0.1" + jest-regex-util "^26.0.0" + jest-util "^26.0.1" + micromatch "^4.0.2" + pirates "^4.0.1" + slash "^3.0.0" + source-map "^0.6.1" + write-file-atomic "^3.0.0" + +"@jest/types@^25.5.0": + version "25.5.0" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-25.5.0.tgz#4d6a4793f7b9599fc3680877b856a97dbccf2a9d" + integrity sha512-OXD0RgQ86Tu3MazKo8bnrkDRaDXXMGUqd+kTtLtK1Zb7CRzQcaSRPPPV37SvYTdevXEBVxe0HXylEjs8ibkmCw== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^1.1.1" + "@types/yargs" "^15.0.0" + chalk "^3.0.0" + +"@jest/types@^26.0.1": + version "26.0.1" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.0.1.tgz#b78333fbd113fa7aec8d39de24f88de8686dac67" + integrity sha512-IbtjvqI9+eS1qFnOIEL7ggWmT+iK/U+Vde9cGWtYb/b6XgKb3X44ZAe/z9YZzoAAZ/E92m0DqrilF934IGNnQA== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^1.1.1" + "@types/yargs" "^15.0.0" + chalk "^4.0.0" + "@nodelib/fs.scandir@2.1.3": version "2.1.3" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b" @@ -1375,17 +2580,176 @@ nullthrows "^1.1.1" physical-cpu-count "^2.0.0" +"@sinonjs/commons@^1.7.0": + version "1.8.0" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.0.tgz#c8d68821a854c555bba172f3b06959a0039b236d" + integrity sha512-wEj54PfsZ5jGSwMX68G8ZXFawcSglQSXqCftWX3ec8MDUzQdHgcKvw97awHbY0efQEL5iKUOAmmVtoYgmrSG4Q== + dependencies: + type-detect "4.0.8" + +"@sinonjs/fake-timers@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz#293674fccb3262ac782c7aadfdeca86b10c75c40" + integrity sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA== + dependencies: + "@sinonjs/commons" "^1.7.0" + +"@testing-library/dom@^7.14.2": + version "7.16.2" + resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-7.16.2.tgz#f7a20b5548817e5c7ed26077913372d977be90af" + integrity sha512-4fT5l5L+5gfNhUZVCg0wnSszbRJ7A1ZHEz32v7OzH3mcY5lUsK++brI3IB2L9F5zO4kSDc2TRGEVa8v2hgl9vA== + dependencies: + "@babel/runtime" "^7.10.2" + aria-query "^4.0.2" + dom-accessibility-api "^0.4.5" + pretty-format "^25.5.0" + +"@testing-library/jest-dom@^5.10.1": + version "5.10.1" + resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.10.1.tgz#6508a9f007bd74e5d3c0b3135b668027ab663989" + integrity sha512-uv9lLAnEFRzwUTN/y9lVVXVXlEzazDkelJtM5u92PsGkEasmdI+sfzhZHxSDzlhZVTrlLfuMh2safMr8YmzXLg== + dependencies: + "@babel/runtime" "^7.9.2" + "@types/testing-library__jest-dom" "^5.9.1" + chalk "^3.0.0" + css "^2.2.4" + css.escape "^1.5.1" + jest-diff "^25.1.0" + jest-matcher-utils "^25.1.0" + lodash "^4.17.15" + redent "^3.0.0" + +"@testing-library/react@^10.3.0": + version "10.3.0" + resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-10.3.0.tgz#d615385b8d86ef4d76142a423755d471b3673295" + integrity sha512-Rhn5uJK6lYHWzlGVbK6uAvheAW8AUoFYxTLGdDxgsJDaK/PYy5drWfW/6YpMMOKMw+u6jHHl4MNHlt5qLHnm0Q== + dependencies: + "@babel/runtime" "^7.10.2" + "@testing-library/dom" "^7.14.2" + +"@types/babel__core@^7.1.7": + version "7.1.9" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.9.tgz#77e59d438522a6fb898fa43dc3455c6e72f3963d" + integrity sha512-sY2RsIJ5rpER1u3/aQ8OFSI7qGIy8o1NEEbgb2UaJcvOtXOMpd39ko723NBpjQFg9SIX7TXtjejZVGeIMLhoOw== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + "@types/babel__generator" "*" + "@types/babel__template" "*" + "@types/babel__traverse" "*" + +"@types/babel__generator@*": + version "7.6.1" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.1.tgz#4901767b397e8711aeb99df8d396d7ba7b7f0e04" + integrity sha512-bBKm+2VPJcMRVwNhxKu8W+5/zT7pwNEqeokFOmbvVSqGzFneNxYcEBro9Ac7/N9tlsaPYnZLK8J1LWKkMsLAew== + dependencies: + "@babel/types" "^7.0.0" + +"@types/babel__template@*": + version "7.0.2" + resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.0.2.tgz#4ff63d6b52eddac1de7b975a5223ed32ecea9307" + integrity sha512-/K6zCpeW7Imzgab2bLkLEbz0+1JlFSrUMdw7KoIIu+IUdu51GWaBZpd3y1VXGVXzynvGa4DaIaxNZHiON3GXUg== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + +"@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": + version "7.0.12" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.0.12.tgz#22f49a028e69465390f87bb103ebd61bd086b8f5" + integrity sha512-t4CoEokHTfcyfb4hUaF9oOHu9RmmNWnm1CP0YmMqOOfClKascOmvlEM736vlqeScuGvBDsHkf8R2INd4DWreQA== + dependencies: + "@babel/types" "^7.3.0" + "@types/color-name@^1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== +"@types/graceful-fs@^4.1.2": + version "4.1.3" + resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.3.tgz#039af35fe26bec35003e8d86d2ee9c586354348f" + integrity sha512-AiHRaEB50LQg0pZmm659vNBb9f4SJ0qrAnteuzhSeAUcJKxoYgEnprg/83kppCnc2zvtCKbdZry1a5pVY3lOTQ== + dependencies: + "@types/node" "*" + +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz#4ba8ddb720221f432e443bd5f9117fd22cfd4762" + integrity sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw== + +"@types/istanbul-lib-report@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686" + integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg== + dependencies: + "@types/istanbul-lib-coverage" "*" + +"@types/istanbul-reports@^1.1.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-1.1.2.tgz#e875cc689e47bce549ec81f3df5e6f6f11cfaeb2" + integrity sha512-P/W9yOX/3oPZSpaYOCQzGqgCQRXn0FFO/V8bWrCQs+wLmvVVxk6CRBXALEvNs9OHIatlnlFokfhuDo2ug01ciw== + dependencies: + "@types/istanbul-lib-coverage" "*" + "@types/istanbul-lib-report" "*" + +"@types/jest@*": + version "26.0.0" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-26.0.0.tgz#a6d7573dffa9c68cbbdf38f2e0de26f159e11134" + integrity sha512-/yeMsH9HQ1RLORlXAwoLXe8S98xxvhNtUz3yrgrwbaxYjT+6SFPZZRksmRKRA6L5vsUtSHeN71viDOTTyYAD+g== + dependencies: + jest-diff "^25.2.1" + pretty-format "^25.2.1" + +"@types/node@*": + version "14.0.13" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.13.tgz#ee1128e881b874c371374c1f72201893616417c9" + integrity sha512-rouEWBImiRaSJsVA+ITTFM6ZxibuAlTuNOCyxVbwreu6k6+ujs7DfnU9o+PShFhET78pMBl3eH+AGSI5eOTkPA== + +"@types/normalize-package-data@^2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e" + integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA== + +"@types/parse-json@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" + integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== + +"@types/prettier@^2.0.0": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.0.1.tgz#b6e98083f13faa1e5231bfa3bdb1b0feff536b6d" + integrity sha512-boy4xPNEtiw6N3abRhBi/e7hNvy3Tt8E9ZRAQrwAGzoCGZS/1wjo9KY7JHhnfnEsG5wSjDbymCozUM9a3ea7OQ== + "@types/q@^1.5.1": version "1.5.2" resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8" integrity sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw== -abab@^2.0.0: +"@types/stack-utils@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e" + integrity sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw== + +"@types/testing-library__jest-dom@^5.9.1": + version "5.9.1" + resolved "https://registry.yarnpkg.com/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.9.1.tgz#aba5ee062b7880f69c212ef769389f30752806e5" + integrity sha512-yYn5EKHO3MPEMSOrcAb1dLWY+68CG29LiXKsWmmpVHqoP5+ZRiAVLyUHvPNrO2dABDdUGZvavMsaGpWNjM6N2g== + dependencies: + "@types/jest" "*" + +"@types/yargs-parser@*": + version "15.0.0" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-15.0.0.tgz#cb3f9f741869e20cce330ffbeb9271590483882d" + integrity sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw== + +"@types/yargs@^15.0.0": + version "15.0.5" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.5.tgz#947e9a6561483bdee9adffc983e91a6902af8b79" + integrity sha512-Dk/IDOPtOgubt/IaevIUbTgV7doaKkoorvOyYM2CMwuDyP89bekI7H4xLIwunNYiK9jhCkmc6pUrJk3cj2AB9w== + dependencies: + "@types/yargs-parser" "*" + +abab@^2.0.0, abab@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.3.tgz#623e2075e02eb2d3f2475e49f99c91846467907a" integrity sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg== @@ -1408,11 +2772,24 @@ acorn-globals@^4.3.0: acorn "^6.0.1" acorn-walk "^6.0.1" +acorn-globals@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-6.0.0.tgz#46cdd39f0f8ff08a876619b55f5ac8a6dc770b45" + integrity sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg== + dependencies: + acorn "^7.1.1" + acorn-walk "^7.1.1" + acorn-walk@^6.0.1: version "6.2.0" resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.2.0.tgz#123cb8f3b84c2171f1f7fb252615b1c78a6b1a8c" integrity sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA== +acorn-walk@^7.1.1: + version "7.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" + integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== + acorn@^5.0.0: version "5.7.3" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" @@ -1423,6 +2800,11 @@ acorn@^6.0.1, acorn@^6.0.4: resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.0.tgz#b659d2ffbafa24baf5db1cdbb2c94a983ecd2784" integrity sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw== +acorn@^7.1.1: + version "7.3.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.3.1.tgz#85010754db53c3fbaf3b9ea3e083aa5c5d147ffd" + integrity sha512-tLc0wSnatxAQHVHUapaHdz72pi9KUyHjq5KyHjGg9Y8Ifdc79pTh2XvI6I1/chZbnM7QtNKzh66ooDogPZSleA== + ajv@^6.5.5: version "6.10.2" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.2.tgz#d3cea04d6b017b2894ad69040fec8b623eb4bd52" @@ -1495,6 +2877,22 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: "@types/color-name" "^1.1.1" color-convert "^2.0.1" +anymatch@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" + integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== + dependencies: + micromatch "^3.1.4" + normalize-path "^2.1.1" + +anymatch@^3.0.3: + version "3.1.1" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142" + integrity sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + aproba@^1.0.3: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" @@ -1515,6 +2913,14 @@ argparse@^1.0.7: dependencies: sprintf-js "~1.0.2" +aria-query@^4.0.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-4.2.2.tgz#0d2ca6c9aceb56b8977e9fed6aed7e15bbd2f83b" + integrity sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA== + dependencies: + "@babel/runtime" "^7.10.2" + "@babel/runtime-corejs3" "^7.10.2" + arr-diff@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" @@ -1624,6 +3030,20 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.0.tgz#24390e6ad61386b0a747265754d2a17219de862c" integrity sha512-Uvq6hVe90D0B2WEnUqtdgY1bATGz3mw33nH9Y+dmA+w5DHvUmBgkr5rM/KCHpCsiFNRUfokW/szpPPgMK2hm4A== +babel-jest@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-26.0.1.tgz#450139ce4b6c17174b136425bda91885c397bc46" + integrity sha512-Z4GGmSNQ8pX3WS1O+6v3fo41YItJJZsVxG5gIQ+HuB/iuAQBJxMTHTwz292vuYws1LnHfwSRgoqI+nxdy/pcvw== + dependencies: + "@jest/transform" "^26.0.1" + "@jest/types" "^26.0.1" + "@types/babel__core" "^7.1.7" + babel-plugin-istanbul "^6.0.0" + babel-preset-jest "^26.0.0" + chalk "^4.0.0" + graceful-fs "^4.2.4" + slash "^3.0.0" + babel-plugin-dynamic-import-node@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz#f00f507bdaa3c3e3ff6e7e5e98d90a7acab96f7f" @@ -1631,6 +3051,93 @@ babel-plugin-dynamic-import-node@^2.3.0: dependencies: object.assign "^4.1.0" +babel-plugin-dynamic-import-node@^2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3" + integrity sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ== + dependencies: + object.assign "^4.1.0" + +babel-plugin-istanbul@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz#e159ccdc9af95e0b570c75b4573b7c34d671d765" + integrity sha512-AF55rZXpe7trmEylbaE1Gv54wn6rwU03aptvRoVIGP8YykoSxqdVLV1TfwflBCE/QtHmqtP8SWlTENqbK8GCSQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@istanbuljs/load-nyc-config" "^1.0.0" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-instrument "^4.0.0" + test-exclude "^6.0.0" + +babel-plugin-jest-hoist@^26.0.0: + version "26.0.0" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.0.0.tgz#fd1d35f95cf8849fc65cb01b5e58aedd710b34a8" + integrity sha512-+AuoehOrjt9irZL7DOt2+4ZaTM6dlu1s5TTS46JBa0/qem4dy7VNW3tMb96qeEqcIh20LD73TVNtmVEeymTG7w== + dependencies: + "@babel/template" "^7.3.3" + "@babel/types" "^7.3.3" + "@types/babel__traverse" "^7.0.6" + +babel-plugin-macros@2.8.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz#0f958a7cc6556b1e65344465d99111a1e5e10138" + integrity sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg== + dependencies: + "@babel/runtime" "^7.7.2" + cosmiconfig "^6.0.0" + resolve "^1.12.0" + +babel-plugin-transform-react-remove-prop-types@0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz#f2edaf9b4c6a5fbe5c1d678bfb531078c1555f3a" + integrity sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA== + +babel-preset-current-node-syntax@^0.1.2: + version "0.1.3" + resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-0.1.3.tgz#b4b547acddbf963cba555ba9f9cbbb70bfd044da" + integrity sha512-uyexu1sVwcdFnyq9o8UQYsXwXflIh8LvrF5+cKrYam93ned1CStffB3+BEcsxGSgagoA3GEyjDqO4a/58hyPYQ== + dependencies: + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-bigint" "^7.8.3" + "@babel/plugin-syntax-class-properties" "^7.8.3" + "@babel/plugin-syntax-import-meta" "^7.8.3" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.8.3" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + +babel-preset-jest@^26.0.0: + version "26.0.0" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-26.0.0.tgz#1eac82f513ad36c4db2e9263d7c485c825b1faa6" + integrity sha512-9ce+DatAa31DpR4Uir8g4Ahxs5K4W4L8refzt+qHWQANb6LhGcAEfIFgLUwk67oya2cCUd6t4eUMtO/z64ocNw== + dependencies: + babel-plugin-jest-hoist "^26.0.0" + babel-preset-current-node-syntax "^0.1.2" + +babel-preset-react-app@^9.1.2: + version "9.1.2" + resolved "https://registry.yarnpkg.com/babel-preset-react-app/-/babel-preset-react-app-9.1.2.tgz#54775d976588a8a6d1a99201a702befecaf48030" + integrity sha512-k58RtQOKH21NyKtzptoAvtAODuAJJs3ZhqBMl456/GnXEQ/0La92pNmwgWoMn5pBTrsvk3YYXdY7zpY4e3UIxA== + dependencies: + "@babel/core" "7.9.0" + "@babel/plugin-proposal-class-properties" "7.8.3" + "@babel/plugin-proposal-decorators" "7.8.3" + "@babel/plugin-proposal-nullish-coalescing-operator" "7.8.3" + "@babel/plugin-proposal-numeric-separator" "7.8.3" + "@babel/plugin-proposal-optional-chaining" "7.9.0" + "@babel/plugin-transform-flow-strip-types" "7.9.0" + "@babel/plugin-transform-react-display-name" "7.8.3" + "@babel/plugin-transform-runtime" "7.9.0" + "@babel/preset-env" "7.9.0" + "@babel/preset-react" "7.9.1" + "@babel/preset-typescript" "7.9.0" + "@babel/runtime" "7.9.0" + babel-plugin-macros "2.8.0" + babel-plugin-transform-react-remove-prop-types "0.4.24" + babel-runtime@^6.11.6, babel-runtime@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" @@ -1768,6 +3275,11 @@ browser-process-hrtime@^0.1.2: resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz#616f00faef1df7ec1b5bf9cfe2bdc3170f26c7b4" integrity sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw== +browser-process-hrtime@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" + integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== + browserify-aes@^1.0.0, browserify-aes@^1.0.4: version "1.2.0" resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" @@ -1836,6 +3348,23 @@ browserslist@^4.0.0, browserslist@^4.6.0, browserslist@^4.6.6, browserslist@^4.8 electron-to-chromium "^1.3.322" node-releases "^1.1.44" +browserslist@^4.12.0, browserslist@^4.8.5, browserslist@^4.9.1: + version "4.12.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.12.0.tgz#06c6d5715a1ede6c51fc39ff67fd647f740b656d" + integrity sha512-UH2GkcEDSI0k/lRkuDSzFl9ZZ87skSy9w2XAn1MsZnL+4c4rqbBd3e82UWHbYDpztABrPBhZsTEeuxVfHppqDg== + dependencies: + caniuse-lite "^1.0.30001043" + electron-to-chromium "^1.3.413" + node-releases "^1.1.53" + pkg-up "^2.0.0" + +bser@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" + integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== + dependencies: + node-int64 "^0.4.0" + buffer-equal@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-0.0.1.tgz#91bc74b11ea405bc916bc6aa908faafa5b4aac4b" @@ -1899,11 +3428,21 @@ callsites@^2.0.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA= -camelcase@^5.0.0: +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +camelcase@^5.0.0, camelcase@^5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== +camelcase@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.0.0.tgz#5259f7c30e35e278f1bdc2a4d91230b37cad981e" + integrity sha512-8KMDF1Vz2gzOq54ONPJS65IvTUaB1cHJ2DMM7MbPmLZljDH1qpzzLsWdiN9pHh6qvkRVDTi/07+eNGch/oLU4w== + caniuse-api@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0" @@ -1919,6 +3458,18 @@ caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001017: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001019.tgz#857e3fccaad2b2feb3f1f6d8a8f62d747ea648e1" integrity sha512-6ljkLtF1KM5fQ+5ZN0wuyVvvebJxgJPTmScOMaFuQN2QuOzvRJnWSKfzQskQU5IOU4Gap3zasYPIinzwUjoj/g== +caniuse-lite@^1.0.30001043: + version "1.0.30001085" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001085.tgz#bed28bd51ff7425d33ee23e730c7f3b703711db6" + integrity sha512-x0YRFRE0pmOD90z+9Xk7jwO58p4feVNXP+U8kWV+Uo/HADyrgESlepzIkUqPgaXkpyceZU6siM1gsK7sHgplqA== + +capture-exit@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4" + integrity sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g== + dependencies: + rsvp "^4.8.4" + caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" @@ -1952,6 +3503,19 @@ chalk@^3.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" +chalk@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" + integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +char-regex@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" + integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== + chownr@^1.1.1: version "1.1.3" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.3.tgz#42d837d5239688d55f303003a508230fa6727142" @@ -2033,6 +3597,15 @@ cliui@^5.0.0: strip-ansi "^5.2.0" wrap-ansi "^5.1.0" +cliui@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" + integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^6.2.0" + clone@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" @@ -2043,6 +3616,11 @@ clones@^1.2.0: resolved "https://registry.yarnpkg.com/clones/-/clones-1.2.0.tgz#b34c872045446a9f264ccceb7731bca05c529b71" integrity sha512-FXDYw4TjR8wgPZYui2LeTqWh1BLpfQ8lB6upMtlpDF6WlOOxghmTTxWyngdKTgozqBgKnHbTVwTE+hOHqAykuQ== +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= + coa@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.2.tgz#43f6c21151b4ef2bf57187db0d73de229e3e7ec3" @@ -2062,6 +3640,11 @@ coffeescript@^2.0.3: resolved "https://registry.yarnpkg.com/coffeescript/-/coffeescript-2.5.0.tgz#9ce853766fa8363384d80f06f79fa8d5b13f566f" integrity sha512-RgTKZhAeKVFuGtce/d3U1x1h5W75AoYFQszNlGrtSIbexC9jowaZo574uUvc9zoNQSDLMWXVtsus9usMtbFU+w== +collect-v8-coverage@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59" + integrity sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg== + collection-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" @@ -2180,7 +3763,7 @@ constants-browserify@^1.0.0: resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= -convert-source-map@^1.5.1, convert-source-map@^1.7.0: +convert-source-map@^1.4.0, convert-source-map@^1.5.1, convert-source-map@^1.6.0, convert-source-map@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== @@ -2200,6 +3783,19 @@ core-js-compat@^3.6.0: browserslist "^4.8.3" semver "7.0.0" +core-js-compat@^3.6.2: + version "3.6.5" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.6.5.tgz#2a51d9a4e25dfd6e690251aa81f99e3c05481f1c" + integrity sha512-7ItTKOhOZbznhXAQ2g/slGg1PJV5zDO/WdkTwi7UEOJmkvsE32PWvx6mKtDjiMpjnR2CNf6BAD6sSxIlv7ptng== + dependencies: + browserslist "^4.8.5" + semver "7.0.0" + +core-js-pure@^3.0.0: + version "3.6.5" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.6.5.tgz#c79e75f5e38dbc85a662d91eea52b8256d53b813" + integrity sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA== + core-js@^2.4.0: version "2.6.11" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c" @@ -2225,6 +3821,17 @@ cosmiconfig@^5.0.0: js-yaml "^3.13.1" parse-json "^4.0.0" +cosmiconfig@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-6.0.0.tgz#da4fee853c52f6b1e6935f41c1a2fc50bd4a9982" + integrity sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg== + dependencies: + "@types/parse-json" "^4.0.0" + import-fresh "^3.1.0" + parse-json "^5.0.0" + path-type "^4.0.0" + yaml "^1.7.2" + create-ecdh@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff" @@ -2256,7 +3863,7 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: safe-buffer "^5.0.1" sha.js "^2.4.8" -cross-spawn@^6.0.4: +cross-spawn@^6.0.0, cross-spawn@^6.0.4: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== @@ -2267,6 +3874,15 @@ cross-spawn@^6.0.4: shebang-command "^1.2.0" which "^1.2.9" +cross-spawn@^7.0.0: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + crypto-browserify@^3.11.0: version "3.12.0" resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" @@ -2351,6 +3967,21 @@ css-what@^3.2.1: resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.2.1.tgz#f4a8f12421064621b456755e34a03a2c22df5da1" integrity sha512-WwOrosiQTvyms+Ti5ZC5vGEK0Vod3FTt1ca+payZqvKuGJF+dq7bG63DstxtN0dpm6FxY27a/zS3Wten+gEtGw== +css.escape@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/css.escape/-/css.escape-1.5.1.tgz#42e27d4fa04ae32f931a4b4d4191fa9cddee97cb" + integrity sha1-QuJ9T6BK4y+TGktNQZH6nN3ul8s= + +css@^2.2.4: + version "2.2.4" + resolved "https://registry.yarnpkg.com/css/-/css-2.2.4.tgz#c646755c73971f2bba6a601e2cf2fd71b1298929" + integrity sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw== + dependencies: + inherits "^2.0.3" + source-map "^0.6.1" + source-map-resolve "^0.5.2" + urix "^0.1.0" + cssesc@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-0.1.0.tgz#c814903e45623371a0477b40109aaafbeeaddbb4" @@ -2441,11 +4072,16 @@ csso@^4.0.2: dependencies: css-tree "1.0.0-alpha.37" -cssom@0.3.x, cssom@^0.3.4: +cssom@0.3.x, cssom@^0.3.4, cssom@~0.3.6: version "0.3.8" resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== +cssom@^0.4.4: + version "0.4.4" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10" + integrity sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw== + cssstyle@^1.1.1: version "1.4.0" resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-1.4.0.tgz#9d31328229d3c565c61e586b02041a28fccdccf1" @@ -2453,6 +4089,13 @@ cssstyle@^1.1.1: dependencies: cssom "0.3.x" +cssstyle@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-2.3.0.tgz#ff665a0ddbdc31864b09647f34163443d90b0852" + integrity sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A== + dependencies: + cssom "~0.3.6" + d3-hierarchy@^1.1.9: version "1.1.9" resolved "https://registry.yarnpkg.com/d3-hierarchy/-/d3-hierarchy-1.1.9.tgz#2f6bee24caaea43f8dc37545fa01628559647a83" @@ -2474,6 +4117,15 @@ data-urls@^1.1.0: whatwg-mimetype "^2.2.0" whatwg-url "^7.0.0" +data-urls@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b" + integrity sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ== + dependencies: + abab "^2.0.3" + whatwg-mimetype "^2.3.0" + whatwg-url "^8.0.0" + deasync@^0.1.14: version "0.1.19" resolved "https://registry.yarnpkg.com/deasync/-/deasync-0.1.19.tgz#e7ea89fcc9ad483367e8a48fe78f508ca86286e8" @@ -2496,7 +4148,7 @@ debug@^3.0.0: dependencies: ms "^2.1.1" -debug@^4.1.0: +debug@^4.1.0, debug@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== @@ -2508,6 +4160,11 @@ decamelize@^1.2.0: resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= +decimal.js@^10.2.0: + version "10.2.0" + resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.2.0.tgz#39466113a9e036111d02f82489b5fd6b0b5ed231" + integrity sha512-vDPw+rDgn3bZe1+F/pyEwb1oMG2XTlRVgAa6B4KccTEpYgF8w6eQllVbQcfIJnZyvzFtFpxnpGtx8dd7DJp/Rw== + decode-uri-component@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" @@ -2530,6 +4187,11 @@ deep-is@~0.1.3: resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= +deepmerge@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" + integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== + define-properties@^1.1.2, define-properties@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" @@ -2582,6 +4244,21 @@ detect-libc@^1.0.3: resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= +detect-newline@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" + integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== + +diff-sequences@^25.2.6: + version "25.2.6" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-25.2.6.tgz#5f467c00edd35352b7bca46d7927d60e687a76dd" + integrity sha512-Hq8o7+6GaZeoFjtpgvRBUknSXNeJiCx7V9Fr94ZMljNiCr9n9L8H8aJqgWOQiDDGdyn29fRNcDdRVJ5fdyihfg== + +diff-sequences@^26.0.0: + version "26.0.0" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-26.0.0.tgz#0760059a5c287637b842bd7085311db7060e88a6" + integrity sha512-JC/eHYEC3aSS0vZGjuoc4vHA0yAQTzhQQldXMeMF+JlxLGJlCO38Gma82NV9gk1jGFz8mDzUMeaKXvjRRdJ2dg== + diffie-hellman@^5.0.0: version "5.0.3" resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" @@ -2591,6 +4268,11 @@ diffie-hellman@^5.0.0: miller-rabin "^4.0.0" randombytes "^2.0.0" +dom-accessibility-api@^0.4.5: + version "0.4.5" + resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.4.5.tgz#d9c1cefa89f509d8cf132ab5d250004d755e76e3" + integrity sha512-HcPDilI95nKztbVikaN2vzwvmv0sE8Y2ZJFODy/m15n7mGXLeOKGiys9qWVbFbh+aq/KYj2lqMLybBOkYAEXqg== + dom-serializer@0: version "0.2.2" resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51" @@ -2621,6 +4303,13 @@ domexception@^1.0.1: dependencies: webidl-conversions "^4.0.2" +domexception@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/domexception/-/domexception-2.0.1.tgz#fb44aefba793e1574b0af6aed2801d057529f304" + integrity sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg== + dependencies: + webidl-conversions "^5.0.0" + domhandler@^2.3.0: version "2.4.2" resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803" @@ -2693,6 +4382,11 @@ electron-to-chromium@^1.3.322: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.328.tgz#a619575c42f1d5b443103664f25ffa5a80190ee5" integrity sha512-x4XefnFxDxFwaQ01d/pppJP9meWhOIJ/gtI6/4jqkpsadq79uL7NYSaX64naLmJqvzUBjSrO3IM2+1b/W9KdPg== +electron-to-chromium@^1.3.413: + version "1.3.480" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.480.tgz#190ae45074578349a4c4f336fba29e76b20e9ef5" + integrity sha512-wnuUfQCBMAdzu5Xe+F4FjaRK+6ToG6WvwG72s8k/3E6b+hoGVYGiQE7JD1NhiCMcqF3+wV+c2vAnaLGRSSWVqA== + elliptic@^6.0.0: version "6.5.2" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.2.tgz#05c5678d7173c049d8ca433552224a495d0e3762" @@ -2795,6 +4489,11 @@ escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= +escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + escodegen@^1.11.0, escodegen@^1.11.1: version "1.12.1" resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.12.1.tgz#08770602a74ac34c7a90ca9229e7d51e379abc76" @@ -2807,6 +4506,18 @@ escodegen@^1.11.0, escodegen@^1.11.1: optionalDependencies: source-map "~0.6.1" +escodegen@^1.14.1: + version "1.14.2" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.2.tgz#14ab71bf5026c2aa08173afba22c6f3173284a84" + integrity sha512-InuOIiKk8wwuOFg6x9BQXbzjrQhtyXh46K9bqVTPzSo2FnyMBaYGBMC6PhQy7yxxil9vIedFBweQBMK74/7o8A== + dependencies: + esprima "^4.0.1" + estraverse "^4.2.0" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.6.1" + escodegen@~1.9.0: version "1.9.1" resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.9.1.tgz#dbae17ef96c8e4bedb1356f4504fa4cc2f7cb7e2" @@ -2824,7 +4535,7 @@ esprima@^3.1.3: resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" integrity sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM= -esprima@^4.0.0: +esprima@^4.0.0, esprima@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== @@ -2857,6 +4568,44 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: md5.js "^1.3.4" safe-buffer "^5.1.1" +exec-sh@^0.3.2: + version "0.3.4" + resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.3.4.tgz#3a018ceb526cc6f6df2bb504b2bfe8e3a4934ec5" + integrity sha512-sEFIkc61v75sWeOe72qyrqg2Qg0OuLESziUDk/O/z2qgS15y2gWVFrI6f2Qn/qw/0/NCfCEsmNA4zOjkwEZT1A== + +execa@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" + integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== + dependencies: + cross-spawn "^6.0.0" + get-stream "^4.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + +execa@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/execa/-/execa-4.0.2.tgz#ad87fb7b2d9d564f70d2b62d511bee41d5cbb240" + integrity sha512-QI2zLa6CjGWdiQsmSkZoGtDx2N+cQIGb3yNolGTdjSQzydzLgYYf8LRuagp7S7fPimjcrzUDSUFd/MgzELMi4Q== + dependencies: + cross-spawn "^7.0.0" + get-stream "^5.0.0" + human-signals "^1.1.1" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.0" + onetime "^5.1.0" + signal-exit "^3.0.2" + strip-final-newline "^2.0.0" + +exit@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" + integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw= + expand-brackets@^2.1.4: version "2.1.4" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" @@ -2875,6 +4624,18 @@ expand-template@^2.0.3: resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c" integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg== +expect@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/expect/-/expect-26.0.1.tgz#18697b9611a7e2725e20ba3ceadda49bc9865421" + integrity sha512-QcCy4nygHeqmbw564YxNbHTJlXh47dVID2BUP52cZFpLU9zHViMFK6h07cC1wf7GYCTIigTdAXhVua8Yl1FkKg== + dependencies: + "@jest/types" "^26.0.1" + ansi-styles "^4.0.0" + jest-get-type "^26.0.0" + jest-matcher-utils "^26.0.1" + jest-message-util "^26.0.1" + jest-regex-util "^26.0.0" + extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" @@ -2974,6 +4735,13 @@ fault@^1.0.2: dependencies: format "^0.2.2" +fb-watchman@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.1.tgz#fc84fb39d2709cf3ff6d743706157bb5708a8a85" + integrity sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg== + dependencies: + bser "2.1.1" + file-uri-to-path@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" @@ -3014,6 +4782,13 @@ finalhandler@1.1.2: statuses "~1.5.0" unpipe "~1.0.0" +find-up@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= + dependencies: + locate-path "^2.0.0" + find-up@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" @@ -3021,6 +4796,14 @@ find-up@^3.0.0: dependencies: locate-path "^3.0.0" +find-up@^4.0.0, find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + flow-bin@^0.127.0: version "0.127.0" resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.127.0.tgz#0614cff4c1b783beef1feeb7108d536e09d77632" @@ -3079,6 +4862,11 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= +fsevents@^2.1.2: + version "2.1.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" + integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== + function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" @@ -3105,16 +4893,40 @@ generic-names@^2.0.1: dependencies: loader-utils "^1.1.0" +gensync@^1.0.0-beta.1: + version "1.0.0-beta.1" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269" + integrity sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg== + get-caller-file@^2.0.1: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== +get-package-type@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" + integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== + get-port@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/get-port/-/get-port-4.2.0.tgz#e37368b1e863b7629c43c5a323625f95cf24b119" integrity sha512-/b3jarXkH8KJoOMQc3uVGHASwGLPq3gSFJ7tgJm2diza+bydJPTGOibin2steecKeOylE8oY2JERlVWkAJO6yw== +get-stream@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" + integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== + dependencies: + pump "^3.0.0" + +get-stream@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.1.0.tgz#01203cdc92597f9b909067c3e656cc1f4d3c4dc9" + integrity sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw== + dependencies: + pump "^3.0.0" + get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" @@ -3139,7 +4951,7 @@ glob-parent@^5.1.0: dependencies: is-glob "^4.0.1" -glob@^7.1.3, glob@^7.1.4: +glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== @@ -3156,6 +4968,11 @@ globals@^11.1.0: resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== +graceful-fs@^4.2.4: + version "4.2.4" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" + integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== + grapheme-breaker@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/grapheme-breaker/-/grapheme-breaker-0.3.2.tgz#5b9e6b78c3832452d2ba2bb1cb830f96276410ac" @@ -3164,12 +4981,17 @@ grapheme-breaker@^0.3.2: brfs "^1.2.0" unicode-trie "^0.3.1" +growly@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" + integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE= + har-schema@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= -har-validator@~5.1.0: +har-validator@~5.1.0, har-validator@~5.1.3: version "5.1.3" resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080" integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g== @@ -3177,6 +4999,11 @@ har-validator@~5.1.0: ajv "^6.5.5" har-schema "^2.0.0" +harmony-reflect@^1.4.6: + version "1.6.1" + resolved "https://registry.yarnpkg.com/harmony-reflect/-/harmony-reflect-1.6.1.tgz#c108d4f2bb451efef7a37861fdbdae72c9bdefa9" + integrity sha512-WJTeyp0JzGtHcuMsi7rw2VwtkvLa+JyfEKJCFyfcS0+CDkjQ5lHPu7zEhFZP+PDSRrEgXa5Ah0l1MbgbE41XjA== + has-ansi@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" @@ -3282,6 +5109,11 @@ hmac-drbg@^1.0.0: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" +hosted-git-info@^2.1.4: + version "2.8.8" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488" + integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg== + hsl-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/hsl-regex/-/hsl-regex-1.0.0.tgz#d49330c789ed819e276a4c0d272dffa30b18fe6e" @@ -3304,6 +5136,18 @@ html-encoding-sniffer@^1.0.2: dependencies: whatwg-encoding "^1.0.1" +html-encoding-sniffer@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz#42a6dc4fd33f00281176e8b23759ca4e4fa185f3" + integrity sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ== + dependencies: + whatwg-encoding "^1.0.5" + +html-escaper@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== + html-tags@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-1.2.0.tgz#c78de65b5663aa597989dd2b7ab49200d7e4db98" @@ -3368,6 +5212,11 @@ https-browserify@^1.0.0: resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= +human-signals@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" + integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== + iconv-lite@0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" @@ -3380,6 +5229,13 @@ icss-replace-symbols@1.1.0, icss-replace-symbols@^1.1.0: resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded" integrity sha1-Bupvg2ead0njhs/h/oEq5dsiPe0= +identity-obj-proxy@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz#94d2bda96084453ef36fbc5aaec37e0f79f1fc14" + integrity sha1-lNK9qWCERT7zb7xarsN+D3nx/BQ= + dependencies: + harmony-reflect "^1.4.6" + ieee754@^1.1.4: version "1.1.13" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" @@ -3393,6 +5249,32 @@ import-fresh@^2.0.0: caller-path "^2.0.0" resolve-from "^3.0.0" +import-fresh@^3.1.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.2.1.tgz#633ff618506e793af5ac91bf48b72677e15cbe66" + integrity sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +import-local@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.0.2.tgz#a8cfd0431d1de4a2199703d003e3e62364fa6db6" + integrity sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= + +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + indexes-of@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" @@ -3458,13 +5340,18 @@ ink@^2.1.1: wrap-ansi "^6.2.0" yoga-layout-prebuilt "^1.9.3" -invariant@^2.2.2: +invariant@^2.2.2, invariant@^2.2.4: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== dependencies: loose-envify "^1.0.0" +ip-regex@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" + integrity sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk= + is-absolute-url@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6" @@ -3570,6 +5457,11 @@ is-directory@^0.3.1: resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= +is-docker@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.0.0.tgz#2cb0df0e75e2d064fe1864c37cdeacb7b2dcf25b" + integrity sha512-pJEdRugimx4fBMra5z2/5iRdZ63OhYV0vr0Dwm5+xtW4D1FvRkB8hamMIhnWfyJeDdyr/aa7BDyNbtG38VxgoQ== + is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" @@ -3604,6 +5496,11 @@ is-fullwidth-code-point@^3.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== +is-generator-fn@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" + integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== + is-glob@^4.0.0, is-glob@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" @@ -3642,6 +5539,11 @@ is-plain-object@^2.0.3, is-plain-object@^2.0.4: dependencies: isobject "^3.0.1" +is-potential-custom-element-name@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.0.tgz#0c52e54bcca391bb2c494b21e8626d7336c6e397" + integrity sha1-DFLlS8yjkbssSUsh6GJtczbG45c= + is-regex@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.5.tgz#39d589a358bf18967f726967120b8fc1aed74eae" @@ -3654,6 +5556,16 @@ is-resolvable@^1.0.0: resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== +is-stream@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= + +is-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" + integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== + is-svg@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-3.0.0.tgz#9321dbd29c212e5ca99c4fa9794c714bcafa2f75" @@ -3668,7 +5580,7 @@ is-symbol@^1.0.2: dependencies: has-symbols "^1.0.1" -is-typedarray@~1.0.0: +is-typedarray@^1.0.0, is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= @@ -3683,6 +5595,13 @@ is-windows@^1.0.2: resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== +is-wsl@^2.1.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + isarray@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" @@ -3720,6 +5639,432 @@ isstream@~0.1.2: resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= +istanbul-lib-coverage@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz#f5944a37c70b550b02a78a5c3b2055b280cec8ec" + integrity sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg== + +istanbul-lib-instrument@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz#873c6fff897450118222774696a3f28902d77c1d" + integrity sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ== + dependencies: + "@babel/core" "^7.7.5" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.0.0" + semver "^6.3.0" + +istanbul-lib-report@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6" + integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== + dependencies: + istanbul-lib-coverage "^3.0.0" + make-dir "^3.0.0" + supports-color "^7.1.0" + +istanbul-lib-source-maps@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz#75743ce6d96bb86dc7ee4352cf6366a23f0b1ad9" + integrity sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg== + dependencies: + debug "^4.1.1" + istanbul-lib-coverage "^3.0.0" + source-map "^0.6.1" + +istanbul-reports@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.0.2.tgz#d593210e5000683750cb09fc0644e4b6e27fd53b" + integrity sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + +jest-changed-files@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-26.0.1.tgz#1334630c6a1ad75784120f39c3aa9278e59f349f" + integrity sha512-q8LP9Sint17HaE2LjxQXL+oYWW/WeeXMPE2+Op9X3mY8IEGFVc14xRxFjUuXUbcPAlDLhtWdIEt59GdQbn76Hw== + dependencies: + "@jest/types" "^26.0.1" + execa "^4.0.0" + throat "^5.0.0" + +jest-cli@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-26.0.1.tgz#3a42399a4cbc96a519b99ad069a117d955570cac" + integrity sha512-pFLfSOBcbG9iOZWaMK4Een+tTxi/Wcm34geqZEqrst9cZDkTQ1LZ2CnBrTlHWuYAiTMFr0EQeK52ScyFU8wK+w== + dependencies: + "@jest/core" "^26.0.1" + "@jest/test-result" "^26.0.1" + "@jest/types" "^26.0.1" + chalk "^4.0.0" + exit "^0.1.2" + graceful-fs "^4.2.4" + import-local "^3.0.2" + is-ci "^2.0.0" + jest-config "^26.0.1" + jest-util "^26.0.1" + jest-validate "^26.0.1" + prompts "^2.0.1" + yargs "^15.3.1" + +jest-config@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-26.0.1.tgz#096a3d4150afadf719d1fab00e9a6fb2d6d67507" + integrity sha512-9mWKx2L1LFgOXlDsC4YSeavnblN6A4CPfXFiobq+YYLaBMymA/SczN7xYTSmLaEYHZOcB98UdoN4m5uNt6tztg== + dependencies: + "@babel/core" "^7.1.0" + "@jest/test-sequencer" "^26.0.1" + "@jest/types" "^26.0.1" + babel-jest "^26.0.1" + chalk "^4.0.0" + deepmerge "^4.2.2" + glob "^7.1.1" + graceful-fs "^4.2.4" + jest-environment-jsdom "^26.0.1" + jest-environment-node "^26.0.1" + jest-get-type "^26.0.0" + jest-jasmine2 "^26.0.1" + jest-regex-util "^26.0.0" + jest-resolve "^26.0.1" + jest-util "^26.0.1" + jest-validate "^26.0.1" + micromatch "^4.0.2" + pretty-format "^26.0.1" + +jest-diff@^25.1.0, jest-diff@^25.2.1, jest-diff@^25.5.0: + version "25.5.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-25.5.0.tgz#1dd26ed64f96667c068cef026b677dfa01afcfa9" + integrity sha512-z1kygetuPiREYdNIumRpAHY6RXiGmp70YHptjdaxTWGmA085W3iCnXNx0DhflK3vwrKmrRWyY1wUpkPMVxMK7A== + dependencies: + chalk "^3.0.0" + diff-sequences "^25.2.6" + jest-get-type "^25.2.6" + pretty-format "^25.5.0" + +jest-diff@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-26.0.1.tgz#c44ab3cdd5977d466de69c46929e0e57f89aa1de" + integrity sha512-odTcHyl5X+U+QsczJmOjWw5tPvww+y9Yim5xzqxVl/R1j4z71+fHW4g8qu1ugMmKdFdxw+AtQgs5mupPnzcIBQ== + dependencies: + chalk "^4.0.0" + diff-sequences "^26.0.0" + jest-get-type "^26.0.0" + pretty-format "^26.0.1" + +jest-docblock@^26.0.0: + version "26.0.0" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-26.0.0.tgz#3e2fa20899fc928cb13bd0ff68bd3711a36889b5" + integrity sha512-RDZ4Iz3QbtRWycd8bUEPxQsTlYazfYn/h5R65Fc6gOfwozFhoImx+affzky/FFBuqISPTqjXomoIGJVKBWoo0w== + dependencies: + detect-newline "^3.0.0" + +jest-each@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-26.0.1.tgz#633083061619302fc90dd8f58350f9d77d67be04" + integrity sha512-OTgJlwXCAR8NIWaXFL5DBbeS4QIYPuNASkzSwMCJO+ywo9BEa6TqkaSWsfR7VdbMLdgYJqSfQcIyjJCNwl5n4Q== + dependencies: + "@jest/types" "^26.0.1" + chalk "^4.0.0" + jest-get-type "^26.0.0" + jest-util "^26.0.1" + pretty-format "^26.0.1" + +jest-environment-jsdom@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-26.0.1.tgz#217690852e5bdd7c846a4e3b50c8ffd441dfd249" + integrity sha512-u88NJa3aptz2Xix2pFhihRBAatwZHWwSiRLBDBQE1cdJvDjPvv7ZGA0NQBxWwDDn7D0g1uHqxM8aGgfA9Bx49g== + dependencies: + "@jest/environment" "^26.0.1" + "@jest/fake-timers" "^26.0.1" + "@jest/types" "^26.0.1" + jest-mock "^26.0.1" + jest-util "^26.0.1" + jsdom "^16.2.2" + +jest-environment-node@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-26.0.1.tgz#584a9ff623124ff6eeb49e0131b5f7612b310b13" + integrity sha512-4FRBWcSn5yVo0KtNav7+5NH5Z/tEgDLp7VRQVS5tCouWORxj+nI+1tOLutM07Zb2Qi7ja+HEDoOUkjBSWZg/IQ== + dependencies: + "@jest/environment" "^26.0.1" + "@jest/fake-timers" "^26.0.1" + "@jest/types" "^26.0.1" + jest-mock "^26.0.1" + jest-util "^26.0.1" + +jest-get-type@^25.2.6: + version "25.2.6" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-25.2.6.tgz#0b0a32fab8908b44d508be81681487dbabb8d877" + integrity sha512-DxjtyzOHjObRM+sM1knti6or+eOgcGU4xVSb2HNP1TqO4ahsT+rqZg+nyqHWJSvWgKC5cG3QjGFBqxLghiF/Ig== + +jest-get-type@^26.0.0: + version "26.0.0" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-26.0.0.tgz#381e986a718998dbfafcd5ec05934be538db4039" + integrity sha512-zRc1OAPnnws1EVfykXOj19zo2EMw5Hi6HLbFCSjpuJiXtOWAYIjNsHVSbpQ8bDX7L5BGYGI8m+HmKdjHYFF0kg== + +jest-haste-map@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-26.0.1.tgz#40dcc03c43ac94d25b8618075804d09cd5d49de7" + integrity sha512-J9kBl/EdjmDsvyv7CiyKY5+DsTvVOScenprz/fGqfLg/pm1gdjbwwQ98nW0t+OIt+f+5nAVaElvn/6wP5KO7KA== + dependencies: + "@jest/types" "^26.0.1" + "@types/graceful-fs" "^4.1.2" + anymatch "^3.0.3" + fb-watchman "^2.0.0" + graceful-fs "^4.2.4" + jest-serializer "^26.0.0" + jest-util "^26.0.1" + jest-worker "^26.0.0" + micromatch "^4.0.2" + sane "^4.0.3" + walker "^1.0.7" + which "^2.0.2" + optionalDependencies: + fsevents "^2.1.2" + +jest-jasmine2@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-26.0.1.tgz#947c40ee816636ba23112af3206d6fa7b23c1c1c" + integrity sha512-ILaRyiWxiXOJ+RWTKupzQWwnPaeXPIoLS5uW41h18varJzd9/7I0QJGqg69fhTT1ev9JpSSo9QtalriUN0oqOg== + dependencies: + "@babel/traverse" "^7.1.0" + "@jest/environment" "^26.0.1" + "@jest/source-map" "^26.0.0" + "@jest/test-result" "^26.0.1" + "@jest/types" "^26.0.1" + chalk "^4.0.0" + co "^4.6.0" + expect "^26.0.1" + is-generator-fn "^2.0.0" + jest-each "^26.0.1" + jest-matcher-utils "^26.0.1" + jest-message-util "^26.0.1" + jest-runtime "^26.0.1" + jest-snapshot "^26.0.1" + jest-util "^26.0.1" + pretty-format "^26.0.1" + throat "^5.0.0" + +jest-leak-detector@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-26.0.1.tgz#79b19ab3f41170e0a78eb8fa754a116d3447fb8c" + integrity sha512-93FR8tJhaYIWrWsbmVN1pQ9ZNlbgRpfvrnw5LmgLRX0ckOJ8ut/I35CL7awi2ecq6Ca4lL59bEK9hr7nqoHWPA== + dependencies: + jest-get-type "^26.0.0" + pretty-format "^26.0.1" + +jest-matcher-utils@^25.1.0: + version "25.5.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-25.5.0.tgz#fbc98a12d730e5d2453d7f1ed4a4d948e34b7867" + integrity sha512-VWI269+9JS5cpndnpCwm7dy7JtGQT30UHfrnM3mXl22gHGt/b7NkjBqXfbhZ8V4B7ANUsjK18PlSBmG0YH7gjw== + dependencies: + chalk "^3.0.0" + jest-diff "^25.5.0" + jest-get-type "^25.2.6" + pretty-format "^25.5.0" + +jest-matcher-utils@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-26.0.1.tgz#12e1fc386fe4f14678f4cc8dbd5ba75a58092911" + integrity sha512-PUMlsLth0Azen8Q2WFTwnSkGh2JZ8FYuwijC8NR47vXKpsrKmA1wWvgcj1CquuVfcYiDEdj985u5Wmg7COEARw== + dependencies: + chalk "^4.0.0" + jest-diff "^26.0.1" + jest-get-type "^26.0.0" + pretty-format "^26.0.1" + +jest-message-util@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-26.0.1.tgz#07af1b42fc450b4cc8e90e4c9cef11b33ce9b0ac" + integrity sha512-CbK8uQREZ8umUfo8+zgIfEt+W7HAHjQCoRaNs4WxKGhAYBGwEyvxuK81FXa7VeB9pwDEXeeKOB2qcsNVCAvB7Q== + dependencies: + "@babel/code-frame" "^7.0.0" + "@jest/types" "^26.0.1" + "@types/stack-utils" "^1.0.1" + chalk "^4.0.0" + graceful-fs "^4.2.4" + micromatch "^4.0.2" + slash "^3.0.0" + stack-utils "^2.0.2" + +jest-mock@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-26.0.1.tgz#7fd1517ed4955397cf1620a771dc2d61fad8fd40" + integrity sha512-MpYTBqycuPYSY6xKJognV7Ja46/TeRbAZept987Zp+tuJvMN0YBWyyhG9mXyYQaU3SBI0TUlSaO5L3p49agw7Q== + dependencies: + "@jest/types" "^26.0.1" + +jest-pnp-resolver@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.1.tgz#ecdae604c077a7fbc70defb6d517c3c1c898923a" + integrity sha512-pgFw2tm54fzgYvc/OHrnysABEObZCUNFnhjoRjaVOCN8NYc032/gVjPaHD4Aq6ApkSieWtfKAFQtmDKAmhupnQ== + +jest-regex-util@^26.0.0: + version "26.0.0" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-26.0.0.tgz#d25e7184b36e39fd466c3bc41be0971e821fee28" + integrity sha512-Gv3ZIs/nA48/Zvjrl34bf+oD76JHiGDUxNOVgUjh3j890sblXryjY4rss71fPtD/njchl6PSE2hIhvyWa1eT0A== + +jest-resolve-dependencies@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-26.0.1.tgz#607ba7ccc32151d185a477cff45bf33bce417f0b" + integrity sha512-9d5/RS/ft0vB/qy7jct/qAhzJsr6fRQJyGAFigK3XD4hf9kIbEH5gks4t4Z7kyMRhowU6HWm/o8ILqhaHdSqLw== + dependencies: + "@jest/types" "^26.0.1" + jest-regex-util "^26.0.0" + jest-snapshot "^26.0.1" + +jest-resolve@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-26.0.1.tgz#21d1ee06f9ea270a343a8893051aeed940cde736" + integrity sha512-6jWxk0IKZkPIVTvq6s72RH735P8f9eCJW3IM5CX/SJFeKq1p2cZx0U49wf/SdMlhaB/anann5J2nCJj6HrbezQ== + dependencies: + "@jest/types" "^26.0.1" + chalk "^4.0.0" + graceful-fs "^4.2.4" + jest-pnp-resolver "^1.2.1" + jest-util "^26.0.1" + read-pkg-up "^7.0.1" + resolve "^1.17.0" + slash "^3.0.0" + +jest-runner@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-26.0.1.tgz#ea03584b7ae4bacfb7e533d680a575a49ae35d50" + integrity sha512-CApm0g81b49Znm4cZekYQK67zY7kkB4umOlI2Dx5CwKAzdgw75EN+ozBHRvxBzwo1ZLYZ07TFxkaPm+1t4d8jA== + dependencies: + "@jest/console" "^26.0.1" + "@jest/environment" "^26.0.1" + "@jest/test-result" "^26.0.1" + "@jest/types" "^26.0.1" + chalk "^4.0.0" + exit "^0.1.2" + graceful-fs "^4.2.4" + jest-config "^26.0.1" + jest-docblock "^26.0.0" + jest-haste-map "^26.0.1" + jest-jasmine2 "^26.0.1" + jest-leak-detector "^26.0.1" + jest-message-util "^26.0.1" + jest-resolve "^26.0.1" + jest-runtime "^26.0.1" + jest-util "^26.0.1" + jest-worker "^26.0.0" + source-map-support "^0.5.6" + throat "^5.0.0" + +jest-runtime@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-26.0.1.tgz#a121a6321235987d294168e282d52b364d7d3f89" + integrity sha512-Ci2QhYFmANg5qaXWf78T2Pfo6GtmIBn2rRaLnklRyEucmPccmCKvS9JPljcmtVamsdMmkyNkVFb9pBTD6si9Lw== + dependencies: + "@jest/console" "^26.0.1" + "@jest/environment" "^26.0.1" + "@jest/fake-timers" "^26.0.1" + "@jest/globals" "^26.0.1" + "@jest/source-map" "^26.0.0" + "@jest/test-result" "^26.0.1" + "@jest/transform" "^26.0.1" + "@jest/types" "^26.0.1" + "@types/yargs" "^15.0.0" + chalk "^4.0.0" + collect-v8-coverage "^1.0.0" + exit "^0.1.2" + glob "^7.1.3" + graceful-fs "^4.2.4" + jest-config "^26.0.1" + jest-haste-map "^26.0.1" + jest-message-util "^26.0.1" + jest-mock "^26.0.1" + jest-regex-util "^26.0.0" + jest-resolve "^26.0.1" + jest-snapshot "^26.0.1" + jest-util "^26.0.1" + jest-validate "^26.0.1" + slash "^3.0.0" + strip-bom "^4.0.0" + yargs "^15.3.1" + +jest-serializer@^26.0.0: + version "26.0.0" + resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-26.0.0.tgz#f6c521ddb976943b93e662c0d4d79245abec72a3" + integrity sha512-sQGXLdEGWFAE4wIJ2ZaIDb+ikETlUirEOBsLXdoBbeLhTHkZUJwgk3+M8eyFizhM6le43PDCCKPA1hzkSDo4cQ== + dependencies: + graceful-fs "^4.2.4" + +jest-snapshot@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-26.0.1.tgz#1baa942bd83d47b837a84af7fcf5fd4a236da399" + integrity sha512-jxd+cF7+LL+a80qh6TAnTLUZHyQoWwEHSUFJjkw35u3Gx+BZUNuXhYvDqHXr62UQPnWo2P6fvQlLjsU93UKyxA== + dependencies: + "@babel/types" "^7.0.0" + "@jest/types" "^26.0.1" + "@types/prettier" "^2.0.0" + chalk "^4.0.0" + expect "^26.0.1" + graceful-fs "^4.2.4" + jest-diff "^26.0.1" + jest-get-type "^26.0.0" + jest-matcher-utils "^26.0.1" + jest-message-util "^26.0.1" + jest-resolve "^26.0.1" + make-dir "^3.0.0" + natural-compare "^1.4.0" + pretty-format "^26.0.1" + semver "^7.3.2" + +jest-util@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-26.0.1.tgz#72c4c51177b695fdd795ca072a6f94e3d7cef00a" + integrity sha512-byQ3n7ad1BO/WyFkYvlWQHTsomB6GIewBh8tlGtusiylAlaxQ1UpS0XYH0ngOyhZuHVLN79Qvl6/pMiDMSSG1g== + dependencies: + "@jest/types" "^26.0.1" + chalk "^4.0.0" + graceful-fs "^4.2.4" + is-ci "^2.0.0" + make-dir "^3.0.0" + +jest-validate@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-26.0.1.tgz#a62987e1da5b7f724130f904725e22f4e5b2e23c" + integrity sha512-u0xRc+rbmov/VqXnX3DlkxD74rHI/CfS5xaV2VpeaVySjbb1JioNVOyly5b56q2l9ZKe7bVG5qWmjfctkQb0bA== + dependencies: + "@jest/types" "^26.0.1" + camelcase "^6.0.0" + chalk "^4.0.0" + jest-get-type "^26.0.0" + leven "^3.1.0" + pretty-format "^26.0.1" + +jest-watcher@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-26.0.1.tgz#5b5e3ebbdf10c240e22a98af66d645631afda770" + integrity sha512-pdZPydsS8475f89kGswaNsN3rhP6lnC3/QDCppP7bg1L9JQz7oU9Mb/5xPETk1RHDCWeqmVC47M4K5RR7ejxFw== + dependencies: + "@jest/test-result" "^26.0.1" + "@jest/types" "^26.0.1" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + jest-util "^26.0.1" + string-length "^4.0.1" + +jest-worker@^26.0.0: + version "26.0.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.0.0.tgz#4920c7714f0a96c6412464718d0c58a3df3fb066" + integrity sha512-pPaYa2+JnwmiZjK9x7p9BoZht+47ecFCDFA/CJxspHzeDvQcfVBLWzCiWyo+EGrSiQMWZtCFo9iSvMZnAAo8vw== + dependencies: + merge-stream "^2.0.0" + supports-color "^7.0.0" + +jest@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/jest/-/jest-26.0.1.tgz#5c51a2e58dff7525b65f169721767173bf832694" + integrity sha512-29Q54kn5Bm7ZGKIuH2JRmnKl85YRigp0o0asTc6Sb6l2ch1DCXIeZTLLFy9ultJvhkTqbswF5DEx4+RlkmCxWg== + dependencies: + "@jest/core" "^26.0.1" + import-local "^3.0.2" + jest-cli "^26.0.1" + js-beautify@^1.8.9: version "1.10.2" resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.10.2.tgz#88c9099cd6559402b124cfab18754936f8a7b178" @@ -3786,6 +6131,38 @@ jsdom@^14.1.0: ws "^6.1.2" xml-name-validator "^3.0.0" +jsdom@^16.2.2: + version "16.2.2" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.2.2.tgz#76f2f7541646beb46a938f5dc476b88705bedf2b" + integrity sha512-pDFQbcYtKBHxRaP55zGXCJWgFHkDAYbKcsXEK/3Icu9nKYZkutUXfLBwbD+09XDutkYSHcgfQLZ0qvpAAm9mvg== + dependencies: + abab "^2.0.3" + acorn "^7.1.1" + acorn-globals "^6.0.0" + cssom "^0.4.4" + cssstyle "^2.2.0" + data-urls "^2.0.0" + decimal.js "^10.2.0" + domexception "^2.0.1" + escodegen "^1.14.1" + html-encoding-sniffer "^2.0.1" + is-potential-custom-element-name "^1.0.0" + nwsapi "^2.2.0" + parse5 "5.1.1" + request "^2.88.2" + request-promise-native "^1.0.8" + saxes "^5.0.0" + symbol-tree "^3.2.4" + tough-cookie "^3.0.1" + w3c-hr-time "^1.0.2" + w3c-xmlserializer "^2.0.0" + webidl-conversions "^6.0.0" + whatwg-encoding "^1.0.5" + whatwg-mimetype "^2.3.0" + whatwg-url "^8.0.0" + ws "^7.2.3" + xml-name-validator "^3.0.0" + jsesc@^2.5.1: version "2.5.2" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" @@ -3835,6 +6212,13 @@ json5@^2.1.0: dependencies: minimist "^1.2.0" +json5@^2.1.2: + version "2.1.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.3.tgz#c9b0f7fa9233bfe5807fe66fcf3a5617ed597d43" + integrity sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA== + dependencies: + minimist "^1.2.5" + jsprim@^1.2.2: version "1.4.1" resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" @@ -3869,6 +6253,23 @@ kind-of@^6.0.0, kind-of@^6.0.2: resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== +kleur@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" + integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== + +leven@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" + integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== + +levenary@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/levenary/-/levenary-1.1.1.tgz#842a9ee98d2075aa7faeedbe32679e9205f46f77" + integrity sha512-mkAdOIt79FD6irqjYSs4rdbnlT5vRonMEvBVPVb3XmevfS8kgRXwfes0dhPdEtzTWD/1eNE/Bm/G1iRt6DcnQQ== + dependencies: + leven "^3.1.0" + levn@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" @@ -3877,6 +6278,11 @@ levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" +lines-and-columns@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" + integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= + loader-utils@^1.1.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" @@ -3886,6 +6292,14 @@ loader-utils@^1.1.0: emojis-list "^3.0.0" json5 "^1.0.1" +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + locate-path@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" @@ -3894,6 +6308,13 @@ locate-path@^3.0.0: p-locate "^3.0.0" path-exists "^3.0.0" +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + lodash.camelcase@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" @@ -3973,6 +6394,20 @@ magic-string@^0.22.4: dependencies: vlq "^0.2.2" +make-dir@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + +makeerror@1.0.x: + version "1.0.11" + resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c" + integrity sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw= + dependencies: + tmpl "1.0.x" + map-cache@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" @@ -4011,12 +6446,17 @@ merge-source-map@1.0.4: dependencies: source-map "^0.5.6" +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + merge2@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.3.0.tgz#5b366ee83b2f1582c48f87e47cf1a9352103ca81" integrity sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw== -micromatch@^3.0.4, micromatch@^3.1.10: +micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== @@ -4083,6 +6523,11 @@ mimic-response@^2.0.0: resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.0.0.tgz#996a51c60adf12cb8a87d7fb8ef24c2f3d5ebb46" integrity sha512-8ilDoEapqA4uQ3TwS0jakGONKXVJqpy+RpM+3b7pLdOjghCrEiGp9SRkFbUHAmZW9vdnrENWHjaweIoTIJExSQ== +min-indent@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" + integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== + minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" @@ -4105,6 +6550,11 @@ minimist@0.0.8: resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= +minimist@^1.1.1, minimist@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + minimist@^1.1.3, minimist@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" @@ -4157,6 +6607,11 @@ napi-build-utils@^1.0.1: resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.1.tgz#1381a0f92c39d66bf19852e7873432fc2123e508" integrity sha512-boQj1WFgQH3v4clhu3mTNfP+vOBxorDlE8EKiMjUlLG3C4qAESnn9AxIOkFgTR2c9LtzNjPrjS60cT27ZKBhaA== +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= + ncp@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ncp/-/ncp-2.0.0.tgz#195a21d6c46e361d2fb1281ba38b91e9df7bdbb3" @@ -4184,6 +6639,11 @@ node-forge@^0.8.1: resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.8.5.tgz#57906f07614dc72762c84cef442f427c0e1b86ee" integrity sha512-vFMQIWt+J/7FLNyKouZ9TazT74PRV3wgv9UT4cRjC8BffxFbKXkgIWR42URCPSnHm/QDz6BOlb2Q0U4+VQT67Q== +node-int64@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" + integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs= + node-libs-browser@^2.0.0, node-libs-browser@^2.1.0: version "2.2.1" resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" @@ -4218,6 +6678,18 @@ node-modules-regexp@^1.0.0: resolved "https://registry.yarnpkg.com/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz#8d9dbe28964a4ac5712e9131642107c71e90ec40" integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA= +node-notifier@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-7.0.1.tgz#a355e33e6bebacef9bf8562689aed0f4230ca6f9" + integrity sha512-VkzhierE7DBmQEElhTGJIoiZa1oqRijOtgOlsXg32KrJRXsPy0NXFBqWGW/wTswnJlDCs5viRYaqWguqzsKcmg== + dependencies: + growly "^1.3.0" + is-wsl "^2.1.1" + semver "^7.2.1" + shellwords "^0.1.1" + uuid "^7.0.3" + which "^2.0.2" + node-releases@^1.1.44: version "1.1.44" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.44.tgz#cd66438a6eb875e3eb012b6a12e48d9f4326ffd7" @@ -4225,6 +6697,11 @@ node-releases@^1.1.44: dependencies: semver "^6.3.0" +node-releases@^1.1.53: + version "1.1.58" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.58.tgz#8ee20eef30fa60e52755fcc0942def5a734fe935" + integrity sha512-NxBudgVKiRh/2aPWMgPR7bPTX0VPmGx5QBwCtdHitnqFE5/O8DeBXuIMH1nwNnw/aMo6AjOrpsHzfY3UbUJ7yg== + noop-logger@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/noop-logger/-/noop-logger-0.1.1.tgz#94a2b1633c4f1317553007d8966fd0e841b6a4c2" @@ -4243,11 +6720,47 @@ normalize-html-whitespace@^1.0.0: resolved "https://registry.yarnpkg.com/normalize-html-whitespace/-/normalize-html-whitespace-1.0.0.tgz#5e3c8e192f1b06c3b9eee4b7e7f28854c7601e34" integrity sha512-9ui7CGtOOlehQu0t/OhhlmDyc71mKVlv+4vF+me4iZLPrNtRL2xoquEdfZxasC/bdQi/Hr3iTrpyRKIG+ocabA== +normalize-package-data@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" + integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== + dependencies: + hosted-git-info "^2.1.4" + resolve "^1.10.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +normalize-path@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= + dependencies: + remove-trailing-separator "^1.0.1" + +normalize-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + normalize-url@^3.0.0: version "3.3.0" resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559" integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg== +npm-run-path@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" + integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= + dependencies: + path-key "^2.0.0" + +npm-run-path@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + npmlog@^4.0.1: version "4.1.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" @@ -4275,7 +6788,7 @@ number-is-nan@^1.0.0: resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= -nwsapi@^2.1.3: +nwsapi@^2.1.3, nwsapi@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7" integrity sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ== @@ -4416,8 +6929,25 @@ osenv@^0.1.4: resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== dependencies: - os-homedir "^1.0.0" - os-tmpdir "^1.0.0" + os-homedir "^1.0.0" + os-tmpdir "^1.0.0" + +p-each-series@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-2.1.0.tgz#961c8dd3f195ea96c747e636b262b800a6b1af48" + integrity sha512-ZuRs1miPT4HrjFa+9fRfOFXxGJfORgelKV9f9nNOWw2gl6gVsRaVDOQP0+MI0G0wGKns1Yacsu0GjOFbTK0JFQ== + +p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= + +p-limit@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" + integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== + dependencies: + p-try "^1.0.0" p-limit@^2.0.0: version "2.2.2" @@ -4426,6 +6956,20 @@ p-limit@^2.0.0: dependencies: p-try "^2.0.0" +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= + dependencies: + p-limit "^1.1.0" + p-locate@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" @@ -4433,6 +6977,18 @@ p-locate@^3.0.0: dependencies: p-limit "^2.0.0" +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-try@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= + p-try@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" @@ -4464,6 +7020,13 @@ parcel@2.0.0-alpha.3.2: react "^16.7.0" v8-compile-cache "^2.0.0" +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + parse-asn1@^5.0.0: version "5.1.5" resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.5.tgz#003271343da58dc94cace494faef3d2147ecea0e" @@ -4484,6 +7047,16 @@ parse-json@^4.0.0: error-ex "^1.3.1" json-parse-better-errors "^1.0.1" +parse-json@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.0.0.tgz#73e5114c986d143efa3712d4ea24db9a4266f60f" + integrity sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-better-errors "^1.0.1" + lines-and-columns "^1.1.6" + parse-ms@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/parse-ms/-/parse-ms-2.1.0.tgz#348565a753d4391fa524029956b172cb7753097d" @@ -4494,6 +7067,11 @@ parse5@5.1.0: resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.0.tgz#c59341c9723f414c452975564c7c00a68d58acd2" integrity sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ== +parse5@5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178" + integrity sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug== + parseurl@~1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" @@ -4514,21 +7092,36 @@ path-exists@^3.0.0: resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= -path-key@^2.0.1: +path-key@^2.0.0, path-key@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= +path-key@^3.0.0, path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + path-parse@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + pbkdf2@^3.0.3: version "3.0.17" resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.17.tgz#976c206530617b14ebb32114239f7b09336e93a6" @@ -4550,18 +7143,37 @@ physical-cpu-count@^2.0.0: resolved "https://registry.yarnpkg.com/physical-cpu-count/-/physical-cpu-count-2.0.0.tgz#18de2f97e4bf7a9551ad7511942b5496f7aba660" integrity sha1-GN4vl+S/epVRrXURlCtUlverpmA= +picomatch@^2.0.4: + version "2.2.2" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" + integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== + picomatch@^2.0.5: version "2.2.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.1.tgz#21bac888b6ed8601f831ce7816e335bc779f0a4a" integrity sha512-ISBaA8xQNmwELC7eOjqFKMESB2VIqt4PPDD0nsS95b/9dZXvVKOlz9keMSnoGGKcOHXfTvDD6WMaRoSc9UuhRA== -pirates@^4.0.0: +pirates@^4.0.0, pirates@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.1.tgz#643a92caf894566f91b2b986d2c66950a8e2fb87" integrity sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA== dependencies: node-modules-regexp "^1.0.0" +pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + +pkg-up@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-2.0.0.tgz#c819ac728059a461cab1c3889a2be3c49a004d7f" + integrity sha1-yBmscoBZpGHKscOImivjxJoATX8= + dependencies: + find-up "^2.1.0" + pn@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb" @@ -4980,6 +7592,26 @@ prettier@^1.19.1: resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb" integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew== +pretty-format@^25.2.1, pretty-format@^25.5.0: + version "25.5.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-25.5.0.tgz#7873c1d774f682c34b8d48b6743a2bf2ac55791a" + integrity sha512-kbo/kq2LQ/A/is0PQwsEHM7Ca6//bGPPvU6UnsdDRSKTWxT/ru/xb88v4BJf6a69H+uTytOEsTusT9ksd/1iWQ== + dependencies: + "@jest/types" "^25.5.0" + ansi-regex "^5.0.0" + ansi-styles "^4.0.0" + react-is "^16.12.0" + +pretty-format@^26.0.1: + version "26.0.1" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.0.1.tgz#a4fe54fe428ad2fd3413ca6bbd1ec8c2e277e197" + integrity sha512-SWxz6MbupT3ZSlL0Po4WF/KujhQaVehijR2blyRDCzk9e45EaYMVhMBn49fnRuHxtkSpXTes1GxNpVmH86Bxfw== + dependencies: + "@jest/types" "^26.0.1" + ansi-regex "^5.0.0" + ansi-styles "^4.0.0" + react-is "^16.12.0" + pretty-ms@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/pretty-ms/-/pretty-ms-7.0.0.tgz#45781273110caf35f55cab21a8a9bd403a233dc0" @@ -4987,7 +7619,7 @@ pretty-ms@^7.0.0: dependencies: parse-ms "^2.1.0" -private@^0.1.6: +private@^0.1.6, private@^0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== @@ -5002,6 +7634,14 @@ process@^0.11.10: resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= +prompts@^2.0.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.3.2.tgz#480572d89ecf39566d2bd3fe2c9fccb7c4c0b068" + integrity sha512-Q06uKs2CkNYVID0VqwfAl9mipo99zkBv/n2JtWY89Yxa3ZabWSrs0e2KTudKVa3peLUvYXMefDqIleLPVUBZMA== + dependencies: + kleur "^3.0.3" + sisteransi "^1.0.4" + prop-types@^15.5.10, prop-types@^15.6.2: version "15.7.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" @@ -5135,6 +7775,11 @@ react-dom@^16.13.1: prop-types "^15.6.2" scheduler "^0.19.1" +react-is@^16.12.0: + version "16.13.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" + integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== + react-is@^16.8.1: version "16.12.0" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.12.0.tgz#2cc0fe0fba742d97fd527c42a13bec4eeb06241c" @@ -5178,6 +7823,25 @@ react@^16.7.0: object-assign "^4.1.1" prop-types "^15.6.2" +read-pkg-up@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" + integrity sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg== + dependencies: + find-up "^4.1.0" + read-pkg "^5.2.0" + type-fest "^0.8.1" + +read-pkg@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" + integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg== + dependencies: + "@types/normalize-package-data" "^2.4.0" + normalize-package-data "^2.5.0" + parse-json "^5.0.0" + type-fest "^0.6.0" + readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.3, readable-stream@~2.3.6: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" @@ -5200,6 +7864,14 @@ readable-stream@^3.0.0, readable-stream@^3.0.1, readable-stream@^3.1.1: string_decoder "^1.1.1" util-deprecate "^1.0.1" +redent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f" + integrity sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg== + dependencies: + indent-string "^4.0.0" + strip-indent "^3.0.0" + regenerate-unicode-properties@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz#ef51e0f0ea4ad424b77bf7cb41f3e015c70a3f0e" @@ -5207,6 +7879,13 @@ regenerate-unicode-properties@^8.1.0: dependencies: regenerate "^1.4.0" +regenerate-unicode-properties@^8.2.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz#e5de7111d655e7ba60c057dbe9ff37c87e65cdec" + integrity sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA== + dependencies: + regenerate "^1.4.0" + regenerate@^1.2.1, regenerate@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" @@ -5217,6 +7896,11 @@ regenerator-runtime@^0.11.0: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== +regenerator-runtime@^0.13.4: + version "0.13.5" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz#d878a1d094b4306d10b9096484b33ebd55e26697" + integrity sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA== + regenerator-transform@^0.14.0: version "0.14.1" resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.1.tgz#3b2fce4e1ab7732c08f665dfdb314749c7ddd2fb" @@ -5224,6 +7908,14 @@ regenerator-transform@^0.14.0: dependencies: private "^0.1.6" +regenerator-transform@^0.14.2: + version "0.14.4" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.4.tgz#5266857896518d1616a78a0479337a30ea974cc7" + integrity sha512-EaJaKPBI9GvKpvUz2mz4fhx7WPgvwRLY9v3hlNHWmAuJHI13T4nwKnNvm5RWJzEdnI5g5UwtOww+S8IdoUC2bw== + dependencies: + "@babel/runtime" "^7.8.4" + private "^0.1.8" + regex-not@^1.0.0, regex-not@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" @@ -5253,6 +7945,18 @@ regexpu-core@^4.6.0: unicode-match-property-ecmascript "^1.0.4" unicode-match-property-value-ecmascript "^1.1.0" +regexpu-core@^4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.7.0.tgz#fcbf458c50431b0bb7b45d6967b8192d91f3d938" + integrity sha512-TQ4KXRnIn6tz6tjnrXEkD/sshygKH/j5KzK86X8MkeHyZ8qst/LZ89j3X4/8HEIfHANTFIP/AbXakeRhWIl5YQ== + dependencies: + regenerate "^1.4.0" + regenerate-unicode-properties "^8.2.0" + regjsgen "^0.5.1" + regjsparser "^0.6.4" + unicode-match-property-ecmascript "^1.0.4" + unicode-match-property-value-ecmascript "^1.2.0" + regjsgen@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" @@ -5263,6 +7967,11 @@ regjsgen@^0.5.0: resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.1.tgz#48f0bf1a5ea205196929c0d9798b42d1ed98443c" integrity sha512-5qxzGZjDs9w4tzT3TPhCJqWdCc3RLYwy9J2NB0nm5Lz+S273lvWcpjaTGHsT1dc6Hhfq41uSEOw8wBmxrKOuyg== +regjsgen@^0.5.1: + version "0.5.2" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.2.tgz#92ff295fb1deecbf6ecdab2543d207e91aa33733" + integrity sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A== + regjsparser@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" @@ -5277,6 +7986,18 @@ regjsparser@^0.6.0: dependencies: jsesc "~0.5.0" +regjsparser@^0.6.4: + version "0.6.4" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.4.tgz#a769f8684308401a66e9b529d2436ff4d0666272" + integrity sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw== + dependencies: + jsesc "~0.5.0" + +remove-trailing-separator@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= + repeat-element@^1.1.2: version "1.1.3" resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" @@ -5294,7 +8015,7 @@ request-promise-core@1.1.3: dependencies: lodash "^4.17.15" -request-promise-native@^1.0.5: +request-promise-native@^1.0.5, request-promise-native@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.8.tgz#a455b960b826e44e2bf8999af64dff2bfe58cb36" integrity sha512-dapwLGqkHtwL5AEbfenuzjTYg35Jd6KPytsC2/TLkVMz8rm+tNt72MGUWT1RP/aYawMpN6HqbNGBQaRcBtjQMQ== @@ -5329,6 +8050,32 @@ request@^2.88.0: tunnel-agent "^0.6.0" uuid "^3.3.2" +request@^2.88.2: + version "2.88.2" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" + integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + har-validator "~5.1.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + oauth-sign "~0.9.0" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.5.0" + tunnel-agent "^0.6.0" + uuid "^3.3.2" + require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" @@ -5344,11 +8091,28 @@ requires-port@^1.0.0: resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= +resolve-cwd@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" + integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== + dependencies: + resolve-from "^5.0.0" + resolve-from@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" integrity sha1-six699nWiBvItuZTM17rywoYh0g= +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + resolve-url@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" @@ -5361,6 +8125,13 @@ resolve@^1.1.5, resolve@^1.12.0, resolve@^1.3.2: dependencies: path-parse "^1.0.6" +resolve@^1.10.0, resolve@^1.17.0, resolve@^1.8.1: + version "1.17.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" + integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== + dependencies: + path-parse "^1.0.6" + restore-cursor@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" @@ -5404,6 +8175,13 @@ rimraf@^2.6.2: dependencies: glob "^7.1.3" +rimraf@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + ripemd160@^2.0.0, ripemd160@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" @@ -5412,6 +8190,11 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: hash-base "^3.0.0" inherits "^2.0.1" +rsvp@^4.8.4: + version "4.8.5" + resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" + integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA== + run-parallel@^1.1.9: version "1.1.9" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" @@ -5446,6 +8229,21 @@ safer-eval@^1.3.0: dependencies: clones "^1.2.0" +sane@^4.0.3: + version "4.1.0" + resolved "https://registry.yarnpkg.com/sane/-/sane-4.1.0.tgz#ed881fd922733a6c461bc189dc2b6c006f3ffded" + integrity sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA== + dependencies: + "@cnakazawa/watch" "^1.0.3" + anymatch "^2.0.0" + capture-exit "^2.0.0" + exec-sh "^0.3.2" + execa "^1.0.0" + fb-watchman "^2.0.0" + micromatch "^3.1.4" + minimist "^1.1.1" + walker "~1.0.5" + sax@~1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" @@ -5458,6 +8256,13 @@ saxes@^3.1.9: dependencies: xmlchars "^2.1.1" +saxes@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/saxes/-/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d" + integrity sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw== + dependencies: + xmlchars "^2.2.0" + scheduler@^0.18.0: version "0.18.0" resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.18.0.tgz#5901ad6659bc1d8f3fdaf36eb7a67b0d6746b1c4" @@ -5474,21 +8279,26 @@ scheduler@^0.19.1: loose-envify "^1.1.0" object-assign "^4.1.1" +"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + semver@7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== -semver@^5.4.1, semver@^5.5.0, semver@^5.6.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - -semver@^6.3.0: +semver@^6.0.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== +semver@^7.2.1, semver@^7.3.2: + version "7.3.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" + integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== + serialize-to-js@^1.1.1: version "1.2.2" resolved "https://registry.yarnpkg.com/serialize-to-js/-/serialize-to-js-1.2.2.tgz#1a567b0c9bf557bc7d7b77b503dfae0a8218d15d" @@ -5537,11 +8347,28 @@ shebang-command@^1.2.0: dependencies: shebang-regex "^1.0.0" +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + shebang-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +shellwords@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" + integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww== + sigmund@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" @@ -5573,6 +8400,16 @@ simple-swizzle@^0.2.2: dependencies: is-arrayish "^0.3.1" +sisteransi@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" + integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + slice-ansi@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-3.0.0.tgz#31ddc10930a1b7e0b67b08c96c2f49b77a789787" @@ -5612,7 +8449,7 @@ snapdragon@^0.8.1: source-map-resolve "^0.5.0" use "^3.1.0" -source-map-resolve@^0.5.0: +source-map-resolve@^0.5.0, source-map-resolve@^0.5.2: version "0.5.3" resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== @@ -5623,6 +8460,14 @@ source-map-resolve@^0.5.0: source-map-url "^0.4.0" urix "^0.1.0" +source-map-support@^0.5.6: + version "0.5.19" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" + integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + source-map-support@~0.5.10, source-map-support@~0.5.12: version "0.5.16" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042" @@ -5651,6 +8496,32 @@ source-map@^0.7.3: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== +spdx-correct@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" + integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" + integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== + +spdx-expression-parse@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" + integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.5" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" + integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q== + split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" @@ -5690,6 +8561,13 @@ stable@^0.1.8: resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== +stack-utils@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.2.tgz#5cf48b4557becb4638d0bc4f21d23f5d19586593" + integrity sha512-0H7QK2ECz3fyZMzQ8rH0j2ykpfbnd20BFtfg/SqVC2+sCTtcw0aDTGB7dk+de4U4uUeuz6nOtJcrkFFLG1B0Rg== + dependencies: + escape-string-regexp "^2.0.0" + static-eval@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/static-eval/-/static-eval-2.0.3.tgz#cb62fc79946bd4d5f623a45ad428233adace4d72" @@ -5767,6 +8645,14 @@ string-length@^3.1.0: astral-regex "^1.0.0" strip-ansi "^5.2.0" +string-length@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.1.tgz#4a973bf31ef77c4edbceadd6af2611996985f8a1" + integrity sha512-PKyXUd0LK0ePjSOnWn34V2uD6acUWev9uy0Ft05k0E8xRW+SKcA0F7eMr7h5xlzfn+4O3N+55rduYyet3Jk+jw== + dependencies: + char-regex "^1.0.2" + strip-ansi "^6.0.0" + string-width@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" @@ -5860,6 +8746,28 @@ strip-ansi@^6.0.0: dependencies: ansi-regex "^5.0.0" +strip-bom@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" + integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== + +strip-eof@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" + integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= + +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + +strip-indent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" + integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ== + dependencies: + min-indent "^1.0.0" + strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" @@ -5900,13 +8808,21 @@ supports-color@^6.1.0: dependencies: has-flag "^3.0.0" -supports-color@^7.1.0: +supports-color@^7.0.0, supports-color@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1" integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g== dependencies: has-flag "^4.0.0" +supports-hyperlinks@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.1.0.tgz#f663df252af5f37c5d49bbd7eeefa9e0b9e59e47" + integrity sha512-zoE5/e+dnEijk6ASB6/qrK+oYdm2do1hjoLWrqUC/8WEIW1gbxFcKuBof7sW8ArN6e+AYvsE8HBGiVRWL/F5CA== + dependencies: + has-flag "^4.0.0" + supports-color "^7.0.0" + svgo@^1.0.0, svgo@^1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.2.tgz#b6dc511c063346c9e415b81e43401145b96d4167" @@ -5926,7 +8842,7 @@ svgo@^1.0.0, svgo@^1.3.2: unquote "~1.1.1" util.promisify "~1.0.0" -symbol-tree@^3.2.2: +symbol-tree@^3.2.2, symbol-tree@^3.2.4: version "3.2.4" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== @@ -5952,6 +8868,14 @@ tar-stream@^2.0.0: inherits "^2.0.3" readable-stream "^3.1.1" +terminal-link@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/terminal-link/-/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994" + integrity sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ== + dependencies: + ansi-escapes "^4.2.1" + supports-hyperlinks "^2.0.0" + terser@^3.7.3: version "3.17.0" resolved "https://registry.yarnpkg.com/terser/-/terser-3.17.0.tgz#f88ffbeda0deb5637f9d24b0da66f4e15ab10cb2" @@ -5970,6 +8894,20 @@ terser@^4.0.0, terser@^4.3.9: source-map "~0.6.1" source-map-support "~0.5.12" +test-exclude@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" + integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== + dependencies: + "@istanbuljs/schema" "^0.1.2" + glob "^7.1.4" + minimatch "^3.0.4" + +throat@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/throat/-/throat-5.0.0.tgz#c5199235803aad18754a667d659b5e72ce16764b" + integrity sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA== + through2@^2.0.0, through2@~2.0.3: version "2.0.5" resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" @@ -5995,6 +8933,11 @@ tiny-inflate@^1.0.0: resolved "https://registry.yarnpkg.com/tiny-inflate/-/tiny-inflate-1.0.3.tgz#122715494913a1805166aaf7c93467933eea26c4" integrity sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw== +tmpl@1.0.x: + version "1.0.4" + resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" + integrity sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE= + to-arraybuffer@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" @@ -6042,7 +8985,7 @@ to-regex@^3.0.1, to-regex@^3.0.2: regex-not "^1.0.2" safe-regex "^1.1.0" -tough-cookie@^2.3.3, tough-cookie@^2.5.0: +tough-cookie@^2.3.3, tough-cookie@^2.5.0, tough-cookie@~2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== @@ -6050,6 +8993,15 @@ tough-cookie@^2.3.3, tough-cookie@^2.5.0: psl "^1.1.28" punycode "^2.1.1" +tough-cookie@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-3.0.1.tgz#9df4f57e739c26930a018184887f4adb7dca73b2" + integrity sha512-yQyJ0u4pZsv9D4clxO69OEjLWYw+jbgspjTue4lTQZLfV0c5l1VmK2y1JK8E9ahdpltPOaAThPcp5nKPUgSnsg== + dependencies: + ip-regex "^2.1.0" + psl "^1.1.28" + punycode "^2.1.1" + tough-cookie@~2.4.3: version "2.4.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" @@ -6065,6 +9017,13 @@ tr46@^1.0.1: dependencies: punycode "^2.1.0" +tr46@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-2.0.2.tgz#03273586def1595ae08fedb38d7733cee91d2479" + integrity sha512-3n1qG+/5kg+jrbTzwAykB5yRYtQCTqOGKq5U5PE3b0a1/mzo6snDhjGS0zJVJunO0NrT3Dg1MLy5TjWP/UJppg== + dependencies: + punycode "^2.1.1" + tslib@^1.9.0: version "1.10.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" @@ -6094,11 +9053,28 @@ type-check@~0.3.2: dependencies: prelude-ls "~1.1.2" +type-detect@4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + +type-fest@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" + integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== + type-fest@^0.8.1: version "0.8.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== +typedarray-to-buffer@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== + dependencies: + is-typedarray "^1.0.0" + typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" @@ -6137,6 +9113,11 @@ unicode-match-property-value-ecmascript@^1.1.0: resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz#5b4b426e08d13a80365e0d657ac7a6c1ec46a277" integrity sha512-hDTHvaBk3RmFzvSl0UVrUmC3PuW9wKVnpoUDYH0JDkSIovzw+J5viQmeYHxVSBptubnr7PbH2e0fnpDRQnQl5g== +unicode-match-property-value-ecmascript@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz#0d91f600eeeb3096aa962b1d6fc88876e64ea531" + integrity sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ== + unicode-property-aliases-ecmascript@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz#a9cc6cc7ce63a0a3023fc99e341b94431d405a57" @@ -6250,11 +9231,33 @@ uuid@^3.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.3.tgz#4568f0216e78760ee1dbf3a4d2cf53e224112866" integrity sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ== +uuid@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.3.tgz#c5c9f2c8cf25dc0a372c4df1441c41f5bd0c680b" + integrity sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg== + v8-compile-cache@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz#e14de37b31a6d194f5690d67efc4e7f6fc6ab30e" integrity sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g== +v8-to-istanbul@^4.1.3: + version "4.1.4" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-4.1.4.tgz#b97936f21c0e2d9996d4985e5c5156e9d4e49cd6" + integrity sha512-Rw6vJHj1mbdK8edjR7+zuJrpDtKIgNdAvTSAcpYfgMIw+u2dPDntD3dgN4XQFLU2/fvFQdzj+EeSGfd/jnY5fQ== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.1" + convert-source-map "^1.6.0" + source-map "^0.7.3" + +validate-npm-package-license@^3.0.1: + version "3.0.4" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + vendors@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.3.tgz#a6467781abd366217c050f8202e7e50cc9eef8c0" @@ -6286,6 +9289,13 @@ w3c-hr-time@^1.0.1: dependencies: browser-process-hrtime "^0.1.2" +w3c-hr-time@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd" + integrity sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ== + dependencies: + browser-process-hrtime "^1.0.0" + w3c-xmlserializer@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-1.1.2.tgz#30485ca7d70a6fd052420a3d12fd90e6339ce794" @@ -6295,11 +9305,35 @@ w3c-xmlserializer@^1.1.2: webidl-conversions "^4.0.2" xml-name-validator "^3.0.0" +w3c-xmlserializer@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz#3e7104a05b75146cc60f564380b7f683acf1020a" + integrity sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA== + dependencies: + xml-name-validator "^3.0.0" + +walker@^1.0.7, walker@~1.0.5: + version "1.0.7" + resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb" + integrity sha1-L3+bj9ENZ3JisYqITijRlhjgKPs= + dependencies: + makeerror "1.0.x" + webidl-conversions@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== +webidl-conversions@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff" + integrity sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA== + +webidl-conversions@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514" + integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w== + whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0" @@ -6321,6 +9355,15 @@ whatwg-url@^7.0.0: tr46 "^1.0.1" webidl-conversions "^4.0.2" +whatwg-url@^8.0.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.1.0.tgz#c628acdcf45b82274ce7281ee31dd3c839791771" + integrity sha512-vEIkwNi9Hqt4TV9RdnaBPNt+E2Sgmo3gePebCRgZ1R7g6d23+53zCTnuB0amKI4AXq6VM8jj2DUAa0S1vjJxkw== + dependencies: + lodash.sortby "^4.7.0" + tr46 "^2.0.2" + webidl-conversions "^5.0.0" + which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" @@ -6338,6 +9381,13 @@ which@^1.2.9: dependencies: isexe "^2.0.0" +which@^2.0.1, which@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + wide-align@^1.1.0: version "1.1.3" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" @@ -6380,6 +9430,16 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= +write-file-atomic@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" + integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== + dependencies: + imurmurhash "^0.1.4" + is-typedarray "^1.0.0" + signal-exit "^3.0.2" + typedarray-to-buffer "^3.1.5" + ws@^6.1.2, ws@^6.2.0: version "6.2.1" resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb" @@ -6387,12 +9447,17 @@ ws@^6.1.2, ws@^6.2.0: dependencies: async-limiter "~1.0.0" +ws@^7.2.3: + version "7.3.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.3.0.tgz#4b2f7f219b3d3737bc1a2fbf145d825b94d38ffd" + integrity sha512-iFtXzngZVXPGgpTlP1rBqsUK82p9tKqsWRPg5L56egiljujJT3vGAYnHANvFxBieXrTFavhzhxW52jnaWV+w2w== + xml-name-validator@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== -xmlchars@^2.1.1: +xmlchars@^2.1.1, xmlchars@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== @@ -6412,6 +9477,11 @@ yallist@^2.1.2: resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= +yaml@^1.7.2: + version "1.10.0" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.0.tgz#3b593add944876077d4d683fee01081bd9fff31e" + integrity sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg== + yargs-parser@^15.0.0: version "15.0.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-15.0.0.tgz#cdd7a97490ec836195f59f3f4dbe5ea9e8f75f08" @@ -6420,6 +9490,14 @@ yargs-parser@^15.0.0: camelcase "^5.0.0" decamelize "^1.2.0" +yargs-parser@^18.1.1: + version "18.1.3" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" + integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + yargs@^14.0.0: version "14.2.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-14.2.2.tgz#2769564379009ff8597cdd38fba09da9b493c4b5" @@ -6437,6 +9515,23 @@ yargs@^14.0.0: y18n "^4.0.0" yargs-parser "^15.0.0" +yargs@^15.3.1: + version "15.3.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.3.1.tgz#9505b472763963e54afe60148ad27a330818e98b" + integrity sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA== + dependencies: + cliui "^6.0.0" + decamelize "^1.2.0" + find-up "^4.1.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^4.2.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^18.1.1" + yoga-layout-prebuilt@^1.9.3: version "1.9.3" resolved "https://registry.yarnpkg.com/yoga-layout-prebuilt/-/yoga-layout-prebuilt-1.9.3.tgz#11e3be29096afe3c284e5d963cc2d628148c1372" From 80dea0450d56df2a32ccf4eb294d59c7eb51cde2 Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Mon, 22 Jun 2020 14:23:35 +0800 Subject: [PATCH 013/116] Fix yarn start Babel error Following https://github.com/facebook/create-react-app/issues/7183#issuecomment-509975452 --- .babelrc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.babelrc b/.babelrc index 7aa30766abb68..aa1bd21c2b638 100644 --- a/.babelrc +++ b/.babelrc @@ -1,3 +1,8 @@ { - "presets": [["react-app", { "flow": true, "typescript": false }]] + "presets": [ + [ + "react-app", + { "absoluteRuntime": false, "flow": true, "typescript": false } + ] + ] } From e027a56ac4ca9d1085edf3e6eb832293f2b05ef5 Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Mon, 22 Jun 2020 14:24:04 +0800 Subject: [PATCH 014/116] Add demo test script --- src/context/__tests__/demo-test.js | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/context/__tests__/demo-test.js diff --git a/src/context/__tests__/demo-test.js b/src/context/__tests__/demo-test.js new file mode 100644 index 0000000000000..9ab90e1ec8666 --- /dev/null +++ b/src/context/__tests__/demo-test.js @@ -0,0 +1,11 @@ +'use strict'; + +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import ContextMenuItem from '../ContextMenuItem'; + +test('renders learn react link', () => { + render(); + const linkElement = screen.getByText(/learn react/i); + expect(linkElement).toBeInTheDocument(); +}); From 87f7a7d49f1fb129bd4b2654f6470fe313944a5d Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Mon, 22 Jun 2020 14:24:07 +0800 Subject: [PATCH 015/116] Revert "Add demo test script" This reverts commit e027a56ac4ca9d1085edf3e6eb832293f2b05ef5. --- src/context/__tests__/demo-test.js | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 src/context/__tests__/demo-test.js diff --git a/src/context/__tests__/demo-test.js b/src/context/__tests__/demo-test.js deleted file mode 100644 index 9ab90e1ec8666..0000000000000 --- a/src/context/__tests__/demo-test.js +++ /dev/null @@ -1,11 +0,0 @@ -'use strict'; - -import React from 'react'; -import { render, screen } from '@testing-library/react'; -import ContextMenuItem from '../ContextMenuItem'; - -test('renders learn react link', () => { - render(); - const linkElement = screen.getByText(/learn react/i); - expect(linkElement).toBeInTheDocument(); -}); From 6c7a9b32766b61f2da3b19a6e27e390cfc71c9a1 Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Mon, 22 Jun 2020 14:25:11 +0800 Subject: [PATCH 016/116] Add yarn test script --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 5fbee0df1d298..439205b679f50 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,8 @@ "scripts": { "build": "parcel build index.html --no-cache", "prettier": "prettier --write '**/*.{js,json,css}'", - "start": "parcel index.html --no-cache" + "start": "parcel index.html --no-cache", + "test": "jest" }, "author": "Brian Vaughn ", "license": "MIT", From 7de190e8e1f7484e83a05c2699ac76f31e9703e3 Mon Sep 17 00:00:00 2001 From: Kartik Choudhary Date: Tue, 23 Jun 2020 06:07:30 +0000 Subject: [PATCH 017/116] Codebase Restructure (#12) * Move constants to constants.js * Reorg, typo fixes * Move more helper funcs to canvasUtils * Move canvas code to canvas * Move helper functions into utils * Run prettier, fix CLI script command * remove unused imports in app.js, rename utils.js * Update renderCanvas.js * prettier CLI fix, move constants to canvas --- package.json | 2 +- src/App.js | 714 +----------------------- src/EventTooltip.js | 8 +- src/canvas/canvasUtils.js | 273 +++++++++ src/{ => canvas}/constants.js | 21 + src/canvas/renderCanvas.js | 478 ++++++++++++++++ src/canvasUtils.js | 48 -- src/tracerbench/trace/index.js | 1 - src/{utils.js => util/getBatchRange.js} | 0 src/{ => util}/preprocessData.js | 0 src/{ => util}/preprocessFlamechart.js | 4 +- src/{ => util}/useInteractiveEvents.js | 2 +- src/{ => util}/usePanAndZoom.js | 4 +- src/{ => util}/useSmartTooltip.js | 0 14 files changed, 805 insertions(+), 750 deletions(-) create mode 100644 src/canvas/canvasUtils.js rename src/{ => canvas}/constants.js (72%) create mode 100644 src/canvas/renderCanvas.js delete mode 100644 src/canvasUtils.js rename src/{utils.js => util/getBatchRange.js} (100%) rename src/{ => util}/preprocessData.js (100%) rename src/{ => util}/preprocessFlamechart.js (83%) rename src/{ => util}/useInteractiveEvents.js (98%) rename src/{ => util}/usePanAndZoom.js (99%) rename src/{ => util}/useSmartTooltip.js (100%) diff --git a/package.json b/package.json index 439205b679f50..02b824682a713 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "0.0.1", "scripts": { "build": "parcel build index.html --no-cache", - "prettier": "prettier --write '**/*.{js,json,css}'", + "prettier": "prettier --write \"**/*.{js,json,css}\"", "start": "parcel index.html --no-cache", "test": "jest" }, diff --git a/src/App.js b/src/App.js index 769fc56628ba6..35d1a8c385a83 100644 --- a/src/App.js +++ b/src/App.js @@ -1,7 +1,7 @@ // @flow import type { TimelineEvent } from './speedscope/import/chrome'; -import type { PanAndZoomState } from './usePanAndZoom'; +import type { PanAndZoomState } from './util/usePanAndZoom'; import { copy } from 'clipboard-js'; import React, { @@ -13,40 +13,37 @@ import React, { } from 'react'; import { unstable_batchedUpdates } from 'react-dom'; import memoize from 'memoize-one'; -import usePanAndZoom, { - durationToWidth, - positionToTimestamp, - timestampToPosition, -} from './usePanAndZoom'; -import { getCanvasContext } from './canvasUtils'; +import usePanAndZoom from './util/usePanAndZoom'; + +import { + getCanvasContext, + getTimeTickInterval, + cachedFlamegraphTextWidths, + trimFlamegraphText, + getHoveredEvent, + getPriorityHeight, +} from './canvas/canvasUtils'; +import { renderCanvas, renderReact } from './canvas/renderCanvas'; + import prettyMilliseconds from 'pretty-ms'; -import { getBatchRange } from './utils'; -import useInteractiveEvents from './useInteractiveEvents'; +import { getBatchRange } from './util/getBatchRange'; import EventTooltip from './EventTooltip'; -import preprocessData from './preprocessData'; -import preprocessFlamechart from './preprocessFlamechart'; +import preprocessData from './util/preprocessData'; +import preprocessFlamechart from './util/preprocessFlamechart'; import styles from './App.css'; import AutoSizer from 'react-virtualized-auto-sizer'; import { - BAR_SPACER_SIZE, - BAR_HEIGHT, COLORS, - SECTION_GUTTER_SIZE, - EVENT_SIZE, - INTERVAL_TIMES, - LABEL_SIZE, - LABEL_FONT_SIZE, - MARKER_GUTTER_SIZE, - MARKER_FONT_SIZE, - MAX_INTERVAL_SIZE_PX, - MARKER_TEXT_PADDING, - MARKER_HEIGHT, - MARKER_TICK_HEIGHT, -} from './constants'; + REACT_PRIORITIES, + FLAMECHART_FRAME_HEIGHT, + LABEL_FIXED_WIDTH, + HEADER_HEIGHT_FIXED, +} from './canvas/constants'; + import { ContextMenu, ContextMenuItem, useContextMenu } from './context'; +// TODO: Add import button but keep a static path until canvas layout is ready import JSON_PATH from 'url:../static/small-devtools.json'; -//import JSON_PATH from 'url:../static/initial-render.json'; const CONTEXT_MENU_ID = 'canvas'; @@ -66,671 +63,6 @@ type ContextMenuContextData = {| state: PanAndZoomState, |}; -const REACT_PRIORITIES = ['unscheduled', 'high', 'normal', 'low']; - -const ROW_CSS_PIXELS_HEIGHT = 16; -const TEXT_CSS_PIXELS_OFFSET_START = 3; -const TEXT_CSS_PIXELS_OFFSET_TOP = 11; -const FONT_SIZE = 10; -const BORDER_OPACITY = 0.4; - -const REACT_GUTTER_SIZE = 4; -const REACT_EVENT_SIZE = 6; -const REACT_WORK_SIZE = 12; -const REACT_EVENT_BORDER_SIZE = 1; -const REACT_PRIORITY_BORDER_SIZE = 1; - -const FLAMECHART_FONT_SIZE = 10; -const FLAMECHART_FRAME_HEIGHT = 16; -const FLAMECHART_TEXT_PADDING = 3; - -const LABEL_FIXED_WIDTH = LABEL_SIZE + REACT_PRIORITY_BORDER_SIZE; -const HEADER_HEIGHT_FIXED = MARKER_HEIGHT + REACT_PRIORITY_BORDER_SIZE; - -// Time mark intervals vary based on the current zoom range and the time it represents. -// In Chrome, these seem to range from 70-140 pixels wide. -// Time wise, they represent intervals of e.g. 1s, 500ms, 200ms, 100ms, 50ms, 20ms. -// Based on zoom, we should determine which amount to actually show. -function getTimeTickInterval(zoomLevel) { - let interval = INTERVAL_TIMES[0]; - for (let i = 0; i < INTERVAL_TIMES.length; i++) { - const currentInteval = INTERVAL_TIMES[i]; - const pixels = currentInteval * zoomLevel; - if (pixels <= MAX_INTERVAL_SIZE_PX) { - interval = currentInteval; - } - } - return interval; -} - -function getHoveredEvent( - schedulerCanvasHeight: number, - data: ReactProfilerData | null, - flamechart: FlamechartData | null, - state: PanAndZoomState -): ReactHoverContextInfo | null { - const { canvasMouseX, canvasMouseY, offsetY } = state; - - if (canvasMouseX < LABEL_FIXED_WIDTH || canvasMouseY < HEADER_HEIGHT_FIXED) { - return null; - } - - if (canvasMouseY + offsetY < schedulerCanvasHeight) { - if (data != null) { - let adjustedCanvasMouseY = canvasMouseY - HEADER_HEIGHT_FIXED + offsetY; - let priorityMinY = HEADER_HEIGHT_FIXED; - let priorityIndex = null; - let priority: ReactPriority = 'unscheduled'; - for (let index = 0; index < REACT_PRIORITIES.length; index++) { - priority = REACT_PRIORITIES[index]; - - const priorityHeight = getPriorityHeight(data, priority); - if ( - adjustedCanvasMouseY >= priorityMinY && - adjustedCanvasMouseY <= priorityMinY + priorityHeight - ) { - priorityIndex = index; - break; - } - priorityMinY += priorityHeight; - } - - if (priorityIndex === null) { - return null; - } - - const baseY = priorityMinY - offsetY; - const eventMinY = baseY + REACT_GUTTER_SIZE / 2; - const eventMaxY = eventMinY + REACT_EVENT_SIZE + REACT_GUTTER_SIZE; - const measureMinY = eventMaxY; - const measureMaxY = measureMinY + REACT_WORK_SIZE + REACT_GUTTER_SIZE; - - let events = null, - measures = null; - if (canvasMouseY >= eventMinY && canvasMouseY <= eventMaxY) { - events = data[priority].events; - } else if (canvasMouseY >= measureMinY && canvasMouseY <= measureMaxY) { - measures = data[priority].measures; - } - - if (events !== null) { - for (let index = events.length - 1; index >= 0; index--) { - const event = events[index]; - const { timestamp } = event; - - const eventX = timestampToPosition(timestamp, state); - const startX = eventX - REACT_EVENT_SIZE / 2; - const stopX = eventX + REACT_EVENT_SIZE / 2; - if (canvasMouseX >= startX && canvasMouseX <= stopX) { - return { - event, - flamechartNode: null, - measure: null, - priorityIndex, - data, - }; - } - } - } else if (measures !== null) { - // Because data ranges may overlap, wew ant to find the last intersecting item. - // This will always be the one on "top" (the one the user is hovering over). - for (let index = measures.length - 1; index >= 0; index--) { - const measure = measures[index]; - const { duration, timestamp } = measure; - - const pointerTime = positionToTimestamp(canvasMouseX, state); - - if (pointerTime >= timestamp && pointerTime <= timestamp + duration) { - return { - event: null, - flamechartNode: null, - measure, - priorityIndex, - data, - }; - } - } - } - } - } else { - if (flamechart !== null) { - const layerIndex = Math.floor( - (canvasMouseY + offsetY - HEADER_HEIGHT_FIXED - schedulerCanvasHeight) / - FLAMECHART_FRAME_HEIGHT - ); - const layer = flamechart.layers[layerIndex]; - - if (layer != null) { - let startIndex = 0; - let stopIndex = layer.length - 1; - while (startIndex <= stopIndex) { - const currentIndex = Math.floor((startIndex + stopIndex) / 2); - const flamechartNode = layer[currentIndex]; - - const { end, start } = flamechartNode; - - const width = durationToWidth((end - start) / 1000, state); - const x = Math.floor(timestampToPosition(start / 1000, state)); - - if (x <= canvasMouseX && x + width >= canvasMouseX) { - return { - event: null, - flamechartNode, - measure: null, - priorityIndex: null, - data, - }; - } - - if (x > canvasMouseX) { - stopIndex = currentIndex - 1; - } else { - startIndex = currentIndex + 1; - } - } - } - } - } - - return null; -} - -const cachedFlamegraphTextWidths = new Map(); -const trimFlamegraphText = (context, text, width) => { - for (let i = text.length - 1; i >= 0; i--) { - const trimmedText = i === text.length - 1 ? text : text.substr(0, i) + '…'; - - let measuredWidth = cachedFlamegraphTextWidths.get(trimmedText); - if (measuredWidth == null) { - measuredWidth = context.measureText(trimmedText).width; - cachedFlamegraphTextWidths.set(trimmedText, measuredWidth); - } - - if (measuredWidth <= width) { - return trimmedText; - } - } - - return null; -}; - -const renderReact = ({ - baseY, - canvasWidth, - context, - eventOrMeasure, - priorityIndex, - showGroupHighlight, - showHoverHighlight, - state, -}) => { - const { timestamp, type } = eventOrMeasure; - const { offsetY } = state; - - let fillStyle = null; - let hoveredFillStyle = null; - let groupSelectedFillStyle = null; - let x, y, width; - - switch (type) { - case 'commit': - case 'render-idle': - case 'render': - case 'layout-effects': - case 'passive-effects': - const { depth, duration } = ((eventOrMeasure: any): ReactMeasure); - - // We could change the max to 0 and just skip over rendering anything that small, - // but this has the effect of making the chart look very empty when zoomed out. - // So long as perf is okay- it might be best to err on the side of showing things. - width = durationToWidth(duration, state); - if (width <= 0) { - return; // Too small to render at this zoom level - } - - x = timestampToPosition(timestamp, state); - if (x + width < 0 || canvasWidth < x) { - return; // Not in view - } - - switch (type) { - case 'commit': - fillStyle = COLORS.REACT_COMMIT; - hoveredFillStyle = COLORS.REACT_COMMIT_HOVER; - groupSelectedFillStyle = COLORS.REACT_COMMIT_SELECTED; - break; - case 'render-idle': - // We could render idle time as diagonal hashes. - // This looks nicer when zoomed in, but not so nice when zoomed out. - // color = context.createPattern(getIdlePattern(), 'repeat'); - fillStyle = COLORS.REACT_IDLE; - hoveredFillStyle = COLORS.REACT_IDLE_HOVER; - groupSelectedFillStyle = COLORS.REACT_IDLE_SELECTED; - break; - case 'render': - fillStyle = COLORS.REACT_RENDER; - hoveredFillStyle = COLORS.REACT_RENDER_HOVER; - groupSelectedFillStyle = COLORS.REACT_RENDER_SELECTED; - break; - case 'layout-effects': - fillStyle = COLORS.REACT_LAYOUT_EFFECTS; - hoveredFillStyle = COLORS.REACT_LAYOUT_EFFECTS_HOVER; - groupSelectedFillStyle = COLORS.REACT_LAYOUT_EFFECTS_SELECTED; - break; - case 'passive-effects': - fillStyle = COLORS.REACT_PASSIVE_EFFECTS; - hoveredFillStyle = COLORS.REACT_PASSIVE_EFFECTS_HOVER; - groupSelectedFillStyle = COLORS.REACT_PASSIVE_EFFECTS_SELECTED; - break; - default: - console.warn(`Unexpected type "${type}"`); - break; - } - - y = baseY + REACT_WORK_SIZE * depth + REACT_GUTTER_SIZE * depth - offsetY; - - const lineWidth = Math.floor(REACT_EVENT_BORDER_SIZE); - - // $FlowFixMe We know these won't be null - context.fillStyle = showHoverHighlight - ? hoveredFillStyle - : showGroupHighlight - ? groupSelectedFillStyle - : fillStyle; - context.fillRect( - Math.floor(x), - Math.floor(y), - Math.floor(width), - REACT_WORK_SIZE - ); - break; - case 'schedule-render': - case 'schedule-state-update': - case 'suspend': - const { isCascading } = ((eventOrMeasure: any): ReactEvent); - - x = timestampToPosition(timestamp, state); - if (x + EVENT_SIZE / 2 < 0 || canvasWidth < x) { - return; // Not in view - } - - switch (type) { - case 'schedule-render': - case 'schedule-state-update': - if (isCascading) { - fillStyle = showHoverHighlight - ? COLORS.REACT_SCHEDULE_CASCADING_HOVER - : COLORS.REACT_SCHEDULE_CASCADING; - } else { - fillStyle = showHoverHighlight - ? COLORS.REACT_SCHEDULE_HOVER - : COLORS.REACT_SCHEDULE; - } - break; - case 'suspend': - fillStyle = showHoverHighlight - ? COLORS.REACT_SUSPEND_HOVER - : COLORS.REACT_SUSPEND; - break; - default: - console.warn(`Unexpected event or measure type "${type}"`); - break; - } - - if (fillStyle !== null) { - const circumference = REACT_EVENT_SIZE; - y = baseY + REACT_EVENT_SIZE / 2 - offsetY; - - context.beginPath(); - context.fillStyle = fillStyle; - context.arc(x, y, circumference / 2, 0, 2 * Math.PI); - context.fill(); - } - break; - default: - console.warn(`Unexpected event or measure type "${type}"`); - break; - } -}; - -// The canvas we're rendering looks a little like the outline below. -// Left labels mark different scheduler REACT_PRIORITIES, -// and top labels mark different times (based on how long the data runs and how zoomed in we are). -// The content in the bottom right area is scrollable, but the top/left labels are fixed. -// -// ┌----------------------------------- -// | t⁰ t¹ t² ... -// ├-------------┬--------------------- -// | unscheduled ┋ -// ├-------------┼--------------------- -// | high ┋ -// ├-------------┼--------------------- -// | normal ┋ -// ├-------------┼--------------------- -// | low ┋ -// ├-------------┼--------------------- -// | ┋ -// | ┋ -// | ┋ -// └-------------┴--------------------- -// -// Because everything we draw on a canvas is drawn on top of what was already there, -// we render the graph in several passes, each pass creating a layer: -// ,──────── -// axis labels → / -// ,──/ -// profiling data → / '─────────── -// ,─ / -// axis marker lines → / '──────────────── -// ,─ / -// background fills → / '───────────────────── -// / -// '────────────────────────── -// -// TODO Passing "state" directly breaks memoization for e.g. mouse moves -const renderCanvas = memoize( - ( - data: ReactProfilerData, - flamechart: FlamechartData | null, - canvas: HTMLCanvasElement | null, - canvasWidth: number, - canvasHeight: number, - schedulerCanvasHeight: number, - state: PanAndZoomState, - hoveredEvent: ReactHoverContextInfo | null - ) => { - const { offsetX, offsetY, zoomLevel } = state; - - const context = getCanvasContext(canvas, canvasHeight, canvasWidth, true); - - // Fill the canvas with the background color - context.fillStyle = COLORS.BACKGROUND; - context.fillRect(0, 0, canvasWidth, canvasHeight); - - // Charting data renders within this region of pixels as "scrollable" content. - // Time markers (top) and priority labels (left) are fixed content. - const scrollableCanvasWidth = canvasWidth - LABEL_FIXED_WIDTH; - - let y = 0; - - const interval = getTimeTickInterval(zoomLevel); - const intervalSize = interval * zoomLevel; - const firstIntervalPosition = - 0 - offsetX + Math.floor(offsetX / intervalSize) * intervalSize; - - // Render all charting data (once it's loaded and processed) within the "scrollable" region. - // TODO (windowing) We can avoid rendering all of this if we've scrolled some of it off screen. - if (data != null) { - // Time markers do not scroll off screen; they are always rendered at a fixed vertical position. - y = HEADER_HEIGHT_FIXED - offsetY; - - let priorityMinY = HEADER_HEIGHT_FIXED; - - REACT_PRIORITIES.forEach((priority, priorityIndex) => { - const currentPriority = data[priority]; - - let baseY = priorityMinY + REACT_GUTTER_SIZE; - - if (currentPriority.events.length > 0) { - currentPriority.events.forEach(event => { - const showHoverHighlight = - hoveredEvent && hoveredEvent.event === event; - renderReact({ - baseY, - canvasWidth, - context, - eventOrMeasure: event, - showGroupHighlight: false, - showHoverHighlight, - priorityIndex, - state, - }); - }); - - // Draw the hovered and/or selected items on top so they stand out. - // This is helpful if there are multiple (overlapping) items close to each other. - if (hoveredEvent !== null && hoveredEvent.event !== null) { - renderReact({ - baseY, - canvasWidth, - context, - eventOrMeasure: hoveredEvent.event, - showGroupHighlight: false, - showHoverHighlight: true, - priorityIndex: hoveredEvent.priorityIndex, - state, - }); - } - - baseY += REACT_EVENT_SIZE + REACT_GUTTER_SIZE; - } - - currentPriority.measures.forEach(measure => { - const showHoverHighlight = - hoveredEvent && hoveredEvent.measure === measure; - const showGroupHighlight = - hoveredEvent && - hoveredEvent.measure !== null && - hoveredEvent.measure.batchUID === measure.batchUID; - renderReact({ - baseY, - canvasWidth, - context, - eventOrMeasure: measure, - priorityIndex, - showGroupHighlight, - showHoverHighlight, - state, - }); - }); - - priorityMinY += getPriorityHeight(data, priority); - }); - } - - // Flame graph data renders below the prioritized React data. - // TODO Timestamp alignment is off by a few hundred me from our user timing marks; why? - if (flamechart !== null) { - context.textAlign = 'left'; - context.textBaseline = 'middle'; - context.font = `${FLAMECHART_FONT_SIZE}px sans-serif`; - - for (let i = 0; i < flamechart.layers.length; i++) { - const nodes = flamechart.layers[i]; - - const y = Math.floor( - HEADER_HEIGHT_FIXED + - schedulerCanvasHeight + - i * FLAMECHART_FRAME_HEIGHT - - offsetY - ); - if ( - y + FLAMECHART_FRAME_HEIGHT < HEADER_HEIGHT_FIXED || - canvasHeight < y - ) { - continue; // Not in view - } - - for (let j = 0; j < nodes.length; j++) { - const { end, node, start } = nodes[j]; - const { name } = node.frame; - - let showHoverHighlight = - hoveredEvent && hoveredEvent.flamechartNode === nodes[j]; - - const width = durationToWidth((end - start) / 1000, state); - if (width <= 0) { - return; // Too small to render at this zoom level - } - - const x = Math.floor(timestampToPosition(start / 1000, state)); - if (x + width < 0 || canvasWidth < x) { - continue; // Not in view - } - - context.fillStyle = showHoverHighlight - ? COLORS.FLAME_GRAPH_HOVER - : COLORS.FLAME_GRAPH; - - context.fillRect( - x, - y, - Math.floor(width - REACT_PRIORITY_BORDER_SIZE), - Math.floor(FLAMECHART_FRAME_HEIGHT - REACT_PRIORITY_BORDER_SIZE) - ); - - if (width > FLAMECHART_TEXT_PADDING * 2) { - const trimmedName = trimFlamegraphText( - context, - name, - width - FLAMECHART_TEXT_PADDING * 2 + (x < 0 ? x : 0) - ); - if (trimmedName !== null) { - context.fillStyle = COLORS.PRIORITY_LABEL; - context.fillText( - trimmedName, - x + FLAMECHART_TEXT_PADDING - (x < 0 ? x : 0), - y + FLAMECHART_FRAME_HEIGHT / 2 - ); - } - } - } - } - } - - // LEFT: Priority labels - // Priority labels do not scroll off screen; they are always rendered at a fixed horizontal position. - // Render them last, on top of everything else, to account for things scrolled beneath them. - y = HEADER_HEIGHT_FIXED - offsetY; - - REACT_PRIORITIES.forEach((priority, priorityIndex) => { - const priorityHeight = getPriorityHeight(data, priority); - - if (priorityHeight === 0) { - return; - } - - context.fillStyle = COLORS.PRIORITY_BACKGROUND; - context.fillRect( - 0, - Math.floor(y), - Math.floor(LABEL_FIXED_WIDTH), - priorityHeight - ); - - context.fillStyle = COLORS.PRIORITY_BORDER; - context.fillRect( - 0, - Math.floor(y + priorityHeight), - canvasWidth, - REACT_PRIORITY_BORDER_SIZE - ); - - context.fillStyle = COLORS.PRIORITY_BORDER; - context.fillRect( - Math.floor(LABEL_FIXED_WIDTH) - REACT_PRIORITY_BORDER_SIZE, - Math.floor(y), - REACT_PRIORITY_BORDER_SIZE, - priorityHeight - ); - - context.fillStyle = COLORS.PRIORITY_LABEL; - context.textAlign = 'left'; - context.textBaseline = 'middle'; - context.font = `${LABEL_FONT_SIZE}px sans-serif`; - context.fillText(priority, 4, y + priorityHeight / 2); - - y += priorityHeight + REACT_PRIORITY_BORDER_SIZE; - }); - - // TOP: Time markers - // Time markers do not scroll off screen; they are always rendered at a fixed vertical position. - // Render them last, on top of everything else, to account for things scrolled beneath them. - y = 0; - - context.fillStyle = COLORS.BACKGROUND; - context.fillRect(0, 0, canvasWidth, HEADER_HEIGHT_FIXED); - - context.fillStyle = COLORS.PRIORITY_BORDER; - context.fillRect(0, MARKER_HEIGHT, canvasWidth, REACT_PRIORITY_BORDER_SIZE); - - // Draw time marker text on top of the priority groupings - for ( - let i = firstIntervalPosition; - i < scrollableCanvasWidth; - i += intervalSize - ) { - if (i > 0) { - const markerTimestamp = positionToTimestamp( - i + LABEL_FIXED_WIDTH, - state - ); - const markerLabel = Math.round(markerTimestamp); - - const x = LABEL_FIXED_WIDTH + i; - - context.fillStyle = COLORS.PRIORITY_BORDER; - context.fillRect( - x, - MARKER_HEIGHT - MARKER_TICK_HEIGHT, - REACT_PRIORITY_BORDER_SIZE, - MARKER_TICK_HEIGHT - ); - - context.fillStyle = COLORS.TIME_MARKER_LABEL; - context.textAlign = 'right'; - context.textBaseline = 'middle'; - context.font = `${MARKER_FONT_SIZE}px sans-serif`; - context.fillText( - `${markerLabel}ms`, - x - MARKER_TEXT_PADDING, - MARKER_HEIGHT / 2 - ); - } - } - } -); - -const cachedPriorityHeights = new Map(); -const getPriorityHeight = ( - data: ReactProfilerData, - priority: ReactPriority -): number => { - if (cachedPriorityHeights.has(priority)) { - // We know the value must be present because we've just checked. - return ((cachedPriorityHeights.get(priority): any): number); - } else { - const numMeasures = data[priority].maxNestedMeasures; - const events = data[priority].events; - - let priorityHeight = 0; - if (numMeasures > 0 && events.length > 0) { - priorityHeight = - REACT_GUTTER_SIZE + - REACT_EVENT_SIZE + - REACT_WORK_SIZE * numMeasures + - REACT_GUTTER_SIZE * numMeasures + - REACT_PRIORITY_BORDER_SIZE; - } else if (numMeasures > 0) { - priorityHeight = - REACT_GUTTER_SIZE + - REACT_WORK_SIZE * numMeasures + - REACT_GUTTER_SIZE * numMeasures + - REACT_PRIORITY_BORDER_SIZE; - } else if (events.length > 0) { - priorityHeight = - REACT_GUTTER_SIZE + - REACT_EVENT_SIZE + - REACT_GUTTER_SIZE + - REACT_PRIORITY_BORDER_SIZE; - } - - cachedPriorityHeights.set(priority, priorityHeight); - - return priorityHeight; - } -}; - function App() { const [data, setData] = useState(null); const [flamechart, setFlamechart] = useState(null); diff --git a/src/EventTooltip.js b/src/EventTooltip.js index 8a1c3c5fc1a8a..39446faef8b59 100644 --- a/src/EventTooltip.js +++ b/src/EventTooltip.js @@ -1,6 +1,6 @@ // @flow -import type { PanAndZoomState } from './usePanAndZoom'; +import type { PanAndZoomState } from './util/usePanAndZoom'; import type { FlamechartFrame } from './speedscope/lib/flamechart'; import type { ReactEvent, @@ -12,9 +12,9 @@ import type { import prettyMilliseconds from 'pretty-ms'; import React, { Fragment, useLayoutEffect, useRef } from 'react'; -import { COLORS } from './constants'; -import { getBatchRange } from './utils'; -import useSmartTooltip from './useSmartTooltip'; +import { COLORS } from './canvas/constants'; +import { getBatchRange } from './util/getBatchRange'; +import useSmartTooltip from './util/useSmartTooltip'; import styles from './EventTooltip.css'; const TOOLTIP_OFFSET = 4; diff --git a/src/canvas/canvasUtils.js b/src/canvas/canvasUtils.js new file mode 100644 index 0000000000000..970365ef865a9 --- /dev/null +++ b/src/canvas/canvasUtils.js @@ -0,0 +1,273 @@ +// @flow +// Contains helper functions for rendering canvas elements + +import memoize from 'memoize-one'; +import { + INTERVAL_TIMES, + MAX_INTERVAL_SIZE_PX, + LABEL_FIXED_WIDTH, + HEADER_HEIGHT_FIXED, + REACT_PRIORITIES, + REACT_GUTTER_SIZE, + REACT_EVENT_SIZE, + REACT_WORK_SIZE, + REACT_PRIORITY_BORDER_SIZE, + FLAMECHART_FRAME_HEIGHT, +} from './constants'; +import usePanAndZoom, { + durationToWidth, + positionToTimestamp, + timestampToPosition, +} from '../util/usePanAndZoom'; + +// hidpi canvas: https://www.html5rocks.com/en/tutorials/canvas/hidpi/ +export function configureRetinaCanvas( + canvas: HTMLCanvasElement, + height: number, + width: number +): number { + const dpr: number = window.devicePixelRatio || 1; + canvas.width = width * dpr; + canvas.height = height * dpr; + canvas.style.width = `${width}px`; + canvas.style.height = `${height}px`; + return dpr; +} + +export const getCanvasContext = memoize( + ( + canvas: HTMLCanvasElement, + height: number, + width: number, + scaleCanvas: boolean = true + ): CanvasRenderingContext2D => { + const context = canvas.getContext('2d', { alpha: false }); + if (scaleCanvas) { + const dpr = configureRetinaCanvas(canvas, height, width); + // Scale all drawing operations by the dpr, so you don't have to worry about the difference. + context.scale(dpr, dpr); + } + return context; + } +); + +export function getCanvasMousePos( + canvas: HTMLCanvasElement, + mouseEvent: MouseEvent +) { + const rect = + canvas instanceof HTMLCanvasElement + ? canvas.getBoundingClientRect() + : { left: 0, top: 0 }; + const canvasMouseX = mouseEvent.clientX - rect.left; + const canvasMouseY = mouseEvent.clientY - rect.top; + + return { canvasMouseX, canvasMouseY }; +} + +// Time mark intervals vary based on the current zoom range and the time it represents. +// In Chrome, these seem to range from 70-140 pixels wide. +// Time wise, they represent intervals of e.g. 1s, 500ms, 200ms, 100ms, 50ms, 20ms. +// Based on zoom, we should determine which amount to actually show. +export function getTimeTickInterval(zoomLevel) { + let interval = INTERVAL_TIMES[0]; + for (let i = 0; i < INTERVAL_TIMES.length; i++) { + const currentInterval = INTERVAL_TIMES[i]; + const pixels = currentInterval * zoomLevel; + if (pixels <= MAX_INTERVAL_SIZE_PX) { + interval = currentInterval; + } + } + return interval; +} + +export const cachedFlamegraphTextWidths = new Map(); +export const trimFlamegraphText = (context, text, width) => { + for (let i = text.length - 1; i >= 0; i--) { + const trimmedText = i === text.length - 1 ? text : text.substr(0, i) + '…'; + + let measuredWidth = cachedFlamegraphTextWidths.get(trimmedText); + if (measuredWidth == null) { + measuredWidth = context.measureText(trimmedText).width; + cachedFlamegraphTextWidths.set(trimmedText, measuredWidth); + } + + if (measuredWidth <= width) { + return trimmedText; + } + } + + return null; +}; + +export function getHoveredEvent( + schedulerCanvasHeight: number, + data: ReactProfilerData | null, + flamechart: FlamechartData | null, + state: PanAndZoomState +): ReactHoverContextInfo | null { + const { canvasMouseX, canvasMouseY, offsetY } = state; + + if (canvasMouseX < LABEL_FIXED_WIDTH || canvasMouseY < HEADER_HEIGHT_FIXED) { + return null; + } + + if (canvasMouseY + offsetY < schedulerCanvasHeight) { + if (data != null) { + let adjustedCanvasMouseY = canvasMouseY - HEADER_HEIGHT_FIXED + offsetY; + let priorityMinY = HEADER_HEIGHT_FIXED; + let priorityIndex = null; + let priority: ReactPriority = 'unscheduled'; + for (let index = 0; index < REACT_PRIORITIES.length; index++) { + priority = REACT_PRIORITIES[index]; + + const priorityHeight = getPriorityHeight(data, priority); + if ( + adjustedCanvasMouseY >= priorityMinY && + adjustedCanvasMouseY <= priorityMinY + priorityHeight + ) { + priorityIndex = index; + break; + } + priorityMinY += priorityHeight; + } + + if (priorityIndex === null) { + return null; + } + + const baseY = priorityMinY - offsetY; + const eventMinY = baseY + REACT_GUTTER_SIZE / 2; + const eventMaxY = eventMinY + REACT_EVENT_SIZE + REACT_GUTTER_SIZE; + const measureMinY = eventMaxY; + const measureMaxY = measureMinY + REACT_WORK_SIZE + REACT_GUTTER_SIZE; + + let events = null, + measures = null; + if (canvasMouseY >= eventMinY && canvasMouseY <= eventMaxY) { + events = data[priority].events; + } else if (canvasMouseY >= measureMinY && canvasMouseY <= measureMaxY) { + measures = data[priority].measures; + } + + if (events !== null) { + for (let index = events.length - 1; index >= 0; index--) { + const event = events[index]; + const { timestamp } = event; + + const eventX = timestampToPosition(timestamp, state); + const startX = eventX - REACT_EVENT_SIZE / 2; + const stopX = eventX + REACT_EVENT_SIZE / 2; + if (canvasMouseX >= startX && canvasMouseX <= stopX) { + return { + event, + flamechartNode: null, + measure: null, + priorityIndex, + data, + }; + } + } + } else if (measures !== null) { + // Because data ranges may overlap, we want to find the last intersecting item. + // This will always be the one on "top" (the one the user is hovering over). + for (let index = measures.length - 1; index >= 0; index--) { + const measure = measures[index]; + const { duration, timestamp } = measure; + + const pointerTime = positionToTimestamp(canvasMouseX, state); + + if (pointerTime >= timestamp && pointerTime <= timestamp + duration) { + return { + event: null, + flamechartNode: null, + measure, + priorityIndex, + data, + }; + } + } + } + } + } else { + if (flamechart !== null) { + const layerIndex = Math.floor( + (canvasMouseY + offsetY - HEADER_HEIGHT_FIXED - schedulerCanvasHeight) / + FLAMECHART_FRAME_HEIGHT + ); + const layer = flamechart.layers[layerIndex]; + + if (layer != null) { + let startIndex = 0; + let stopIndex = layer.length - 1; + while (startIndex <= stopIndex) { + const currentIndex = Math.floor((startIndex + stopIndex) / 2); + const flamechartNode = layer[currentIndex]; + + const { end, start } = flamechartNode; + + const width = durationToWidth((end - start) / 1000, state); + const x = Math.floor(timestampToPosition(start / 1000, state)); + + if (x <= canvasMouseX && x + width >= canvasMouseX) { + return { + event: null, + flamechartNode, + measure: null, + priorityIndex: null, + data, + }; + } + + if (x > canvasMouseX) { + stopIndex = currentIndex - 1; + } else { + startIndex = currentIndex + 1; + } + } + } + } + } + + return null; +} + +const cachedPriorityHeights = new Map(); +export const getPriorityHeight = ( + data: ReactProfilerData, + priority: ReactPriority +): number => { + if (cachedPriorityHeights.has(priority)) { + // We know the value must be present because we've just checked. + return ((cachedPriorityHeights.get(priority): any): number); + } else { + const numMeasures = data[priority].maxNestedMeasures; + const events = data[priority].events; + + let priorityHeight = 0; + if (numMeasures > 0 && events.length > 0) { + priorityHeight = + REACT_GUTTER_SIZE + + REACT_EVENT_SIZE + + REACT_WORK_SIZE * numMeasures + + REACT_GUTTER_SIZE * numMeasures + + REACT_PRIORITY_BORDER_SIZE; + } else if (numMeasures > 0) { + priorityHeight = + REACT_GUTTER_SIZE + + REACT_WORK_SIZE * numMeasures + + REACT_GUTTER_SIZE * numMeasures + + REACT_PRIORITY_BORDER_SIZE; + } else if (events.length > 0) { + priorityHeight = + REACT_GUTTER_SIZE + + REACT_EVENT_SIZE + + REACT_GUTTER_SIZE + + REACT_PRIORITY_BORDER_SIZE; + } + + cachedPriorityHeights.set(priority, priorityHeight); + + return priorityHeight; + } +}; diff --git a/src/constants.js b/src/canvas/constants.js similarity index 72% rename from src/constants.js rename to src/canvas/constants.js index c1080bd15d816..282b79a0a758d 100644 --- a/src/constants.js +++ b/src/canvas/constants.js @@ -36,6 +36,27 @@ export const ZOOM_WHEEL_DELTA_THRESHOLD = 1; export const MIN_ZOOM_LEVEL = 0.25; export const MAX_ZOOM_LEVEL = 1000; +export const REACT_PRIORITIES = ['unscheduled', 'high', 'normal', 'low']; + +export const ROW_CSS_PIXELS_HEIGHT = 16; +export const TEXT_CSS_PIXELS_OFFSET_START = 3; +export const TEXT_CSS_PIXELS_OFFSET_TOP = 11; +export const FONT_SIZE = 10; +export const BORDER_OPACITY = 0.4; + +export const REACT_GUTTER_SIZE = 4; +export const REACT_EVENT_SIZE = 6; +export const REACT_WORK_SIZE = 12; +export const REACT_EVENT_BORDER_SIZE = 1; +export const REACT_PRIORITY_BORDER_SIZE = 1; + +export const FLAMECHART_FONT_SIZE = 10; +export const FLAMECHART_FRAME_HEIGHT = 16; +export const FLAMECHART_TEXT_PADDING = 3; + +export const LABEL_FIXED_WIDTH = LABEL_SIZE + REACT_PRIORITY_BORDER_SIZE; +export const HEADER_HEIGHT_FIXED = MARKER_HEIGHT + REACT_PRIORITY_BORDER_SIZE; + export const COLORS = Object.freeze({ BACKGROUND: '#ffffff', FLAME_GRAPH: '#fff79f', diff --git a/src/canvas/renderCanvas.js b/src/canvas/renderCanvas.js new file mode 100644 index 0000000000000..379206f78cca3 --- /dev/null +++ b/src/canvas/renderCanvas.js @@ -0,0 +1,478 @@ +// @flow + +import React from 'react'; +import memoize from 'memoize-one'; + +import usePanAndZoom, { + durationToWidth, + positionToTimestamp, + timestampToPosition, +} from '../util/usePanAndZoom'; + +import { + getCanvasContext, + getTimeTickInterval, + trimFlamegraphText, + getPriorityHeight, +} from './canvasUtils'; + +import { + COLORS, + EVENT_SIZE, + LABEL_FONT_SIZE, + MARKER_FONT_SIZE, + MARKER_TEXT_PADDING, + MARKER_HEIGHT, + MARKER_TICK_HEIGHT, + REACT_PRIORITIES, + REACT_GUTTER_SIZE, + REACT_EVENT_SIZE, + REACT_WORK_SIZE, + REACT_EVENT_BORDER_SIZE, + REACT_PRIORITY_BORDER_SIZE, + FLAMECHART_FONT_SIZE, + FLAMECHART_FRAME_HEIGHT, + FLAMECHART_TEXT_PADDING, + LABEL_FIXED_WIDTH, + HEADER_HEIGHT_FIXED, +} from './constants'; + +import type { PanAndZoomState } from '../util/usePanAndZoom'; + +// The canvas we're rendering looks a little like the outline below. +// Left labels mark different scheduler REACT_PRIORITIES, +// and top labels mark different times (based on how long the data runs and how zoomed in we are). +// The content in the bottom right area is scrollable, but the top/left labels are fixed. +// +// ┌----------------------------------- +// | t⁰ t¹ t² ... +// ├-------------┬--------------------- +// | unscheduled ┋ +// ├-------------┼--------------------- +// | high ┋ +// ├-------------┼--------------------- +// | normal ┋ +// ├-------------┼--------------------- +// | low ┋ +// ├-------------┼--------------------- +// | ┋ +// | ┋ +// | ┋ +// └-------------┴--------------------- +// +// Because everything we draw on a canvas is drawn on top of what was already there, +// we render the graph in several passes, each pass creating a layer: +// ,──────── +// axis labels → / +// ,──/ +// profiling data → / '─────────── +// ,─ / +// axis marker lines → / '──────────────── +// ,─ / +// background fills → / '───────────────────── +// / +// '────────────────────────── +// + +export const renderReact = ({ + baseY, + canvasWidth, + context, + eventOrMeasure, + priorityIndex, + showGroupHighlight, + showHoverHighlight, + state, +}) => { + const { timestamp, type } = eventOrMeasure; + const { offsetY } = state; + + let fillStyle = null; + let hoveredFillStyle = null; + let groupSelectedFillStyle = null; + let x, y, width; + + switch (type) { + case 'commit': + case 'render-idle': + case 'render': + case 'layout-effects': + case 'passive-effects': + const { depth, duration } = ((eventOrMeasure: any): ReactMeasure); + + // We could change the max to 0 and just skip over rendering anything that small, + // but this has the effect of making the chart look very empty when zoomed out. + // So long as perf is okay- it might be best to err on the side of showing things. + width = durationToWidth(duration, state); + if (width <= 0) { + return; // Too small to render at this zoom level + } + + x = timestampToPosition(timestamp, state); + if (x + width < 0 || canvasWidth < x) { + return; // Not in view + } + + switch (type) { + case 'commit': + fillStyle = COLORS.REACT_COMMIT; + hoveredFillStyle = COLORS.REACT_COMMIT_HOVER; + groupSelectedFillStyle = COLORS.REACT_COMMIT_SELECTED; + break; + case 'render-idle': + // We could render idle time as diagonal hashes. + // This looks nicer when zoomed in, but not so nice when zoomed out. + // color = context.createPattern(getIdlePattern(), 'repeat'); + fillStyle = COLORS.REACT_IDLE; + hoveredFillStyle = COLORS.REACT_IDLE_HOVER; + groupSelectedFillStyle = COLORS.REACT_IDLE_SELECTED; + break; + case 'render': + fillStyle = COLORS.REACT_RENDER; + hoveredFillStyle = COLORS.REACT_RENDER_HOVER; + groupSelectedFillStyle = COLORS.REACT_RENDER_SELECTED; + break; + case 'layout-effects': + fillStyle = COLORS.REACT_LAYOUT_EFFECTS; + hoveredFillStyle = COLORS.REACT_LAYOUT_EFFECTS_HOVER; + groupSelectedFillStyle = COLORS.REACT_LAYOUT_EFFECTS_SELECTED; + break; + case 'passive-effects': + fillStyle = COLORS.REACT_PASSIVE_EFFECTS; + hoveredFillStyle = COLORS.REACT_PASSIVE_EFFECTS_HOVER; + groupSelectedFillStyle = COLORS.REACT_PASSIVE_EFFECTS_SELECTED; + break; + default: + console.warn(`Unexpected type "${type}"`); + break; + } + + y = baseY + REACT_WORK_SIZE * depth + REACT_GUTTER_SIZE * depth - offsetY; + + const lineWidth = Math.floor(REACT_EVENT_BORDER_SIZE); + + // $FlowFixMe We know these won't be null + context.fillStyle = showHoverHighlight + ? hoveredFillStyle + : showGroupHighlight + ? groupSelectedFillStyle + : fillStyle; + context.fillRect( + Math.floor(x), + Math.floor(y), + Math.floor(width), + REACT_WORK_SIZE + ); + break; + case 'schedule-render': + case 'schedule-state-update': + case 'suspend': + const { isCascading } = ((eventOrMeasure: any): ReactEvent); + + x = timestampToPosition(timestamp, state); + if (x + EVENT_SIZE / 2 < 0 || canvasWidth < x) { + return; // Not in view + } + + switch (type) { + case 'schedule-render': + case 'schedule-state-update': + if (isCascading) { + fillStyle = showHoverHighlight + ? COLORS.REACT_SCHEDULE_CASCADING_HOVER + : COLORS.REACT_SCHEDULE_CASCADING; + } else { + fillStyle = showHoverHighlight + ? COLORS.REACT_SCHEDULE_HOVER + : COLORS.REACT_SCHEDULE; + } + break; + case 'suspend': + fillStyle = showHoverHighlight + ? COLORS.REACT_SUSPEND_HOVER + : COLORS.REACT_SUSPEND; + break; + default: + console.warn(`Unexpected event or measure type "${type}"`); + break; + } + + if (fillStyle !== null) { + const circumference = REACT_EVENT_SIZE; + y = baseY + REACT_EVENT_SIZE / 2 - offsetY; + + context.beginPath(); + context.fillStyle = fillStyle; + context.arc(x, y, circumference / 2, 0, 2 * Math.PI); + context.fill(); + } + break; + default: + console.warn(`Unexpected event or measure type "${type}"`); + break; + } +}; + +// TODO Passing "state" directly breaks memoization for e.g. mouse moves +export const renderCanvas = memoize( + ( + data: ReactProfilerData, + flamechart: FlamechartData | null, + canvas: HTMLCanvasElement | null, + canvasWidth: number, + canvasHeight: number, + schedulerCanvasHeight: number, + state: PanAndZoomState, + hoveredEvent: ReactHoverContextInfo | null + ) => { + const { offsetX, offsetY, zoomLevel } = state; + + const context = getCanvasContext(canvas, canvasHeight, canvasWidth, true); + + // Fill the canvas with the background color + context.fillStyle = COLORS.BACKGROUND; + context.fillRect(0, 0, canvasWidth, canvasHeight); + + // Charting data renders within this region of pixels as "scrollable" content. + // Time markers (top) and priority labels (left) are fixed content. + const scrollableCanvasWidth = canvasWidth - LABEL_FIXED_WIDTH; + + let y = 0; + + const interval = getTimeTickInterval(zoomLevel); + const intervalSize = interval * zoomLevel; + const firstIntervalPosition = + 0 - offsetX + Math.floor(offsetX / intervalSize) * intervalSize; + + // Render all charting data (once it's loaded and processed) within the "scrollable" region. + // TODO (windowing) We can avoid rendering all of this if we've scrolled some of it off screen. + if (data != null) { + // Time markers do not scroll off screen; they are always rendered at a fixed vertical position. + y = HEADER_HEIGHT_FIXED - offsetY; + + let priorityMinY = HEADER_HEIGHT_FIXED; + + REACT_PRIORITIES.forEach((priority, priorityIndex) => { + const currentPriority = data[priority]; + + let baseY = priorityMinY + REACT_GUTTER_SIZE; + + if (currentPriority.events.length > 0) { + currentPriority.events.forEach(event => { + const showHoverHighlight = + hoveredEvent && hoveredEvent.event === event; + renderReact({ + baseY, + canvasWidth, + context, + eventOrMeasure: event, + showGroupHighlight: false, + showHoverHighlight, + priorityIndex, + state, + }); + }); + + // Draw the hovered and/or selected items on top so they stand out. + // This is helpful if there are multiple (overlapping) items close to each other. + if (hoveredEvent !== null && hoveredEvent.event !== null) { + renderReact({ + baseY, + canvasWidth, + context, + eventOrMeasure: hoveredEvent.event, + showGroupHighlight: false, + showHoverHighlight: true, + priorityIndex: hoveredEvent.priorityIndex, + state, + }); + } + + baseY += REACT_EVENT_SIZE + REACT_GUTTER_SIZE; + } + + currentPriority.measures.forEach(measure => { + const showHoverHighlight = + hoveredEvent && hoveredEvent.measure === measure; + const showGroupHighlight = + hoveredEvent && + hoveredEvent.measure !== null && + hoveredEvent.measure.batchUID === measure.batchUID; + renderReact({ + baseY, + canvasWidth, + context, + eventOrMeasure: measure, + priorityIndex, + showGroupHighlight, + showHoverHighlight, + state, + }); + }); + + priorityMinY += getPriorityHeight(data, priority); + }); + } + + // Flame graph data renders below the prioritized React data. + // TODO Timestamp alignment is off by a few hundred me from our user timing marks; why? + if (flamechart !== null) { + context.textAlign = 'left'; + context.textBaseline = 'middle'; + context.font = `${FLAMECHART_FONT_SIZE}px sans-serif`; + + for (let i = 0; i < flamechart.layers.length; i++) { + const nodes = flamechart.layers[i]; + + const y = Math.floor( + HEADER_HEIGHT_FIXED + + schedulerCanvasHeight + + i * FLAMECHART_FRAME_HEIGHT - + offsetY + ); + if ( + y + FLAMECHART_FRAME_HEIGHT < HEADER_HEIGHT_FIXED || + canvasHeight < y + ) { + continue; // Not in view + } + + for (let j = 0; j < nodes.length; j++) { + const { end, node, start } = nodes[j]; + const { name } = node.frame; + + let showHoverHighlight = + hoveredEvent && hoveredEvent.flamechartNode === nodes[j]; + + const width = durationToWidth((end - start) / 1000, state); + if (width <= 0) { + return; // Too small to render at this zoom level + } + + const x = Math.floor(timestampToPosition(start / 1000, state)); + if (x + width < 0 || canvasWidth < x) { + continue; // Not in view + } + + context.fillStyle = showHoverHighlight + ? COLORS.FLAME_GRAPH_HOVER + : COLORS.FLAME_GRAPH; + + context.fillRect( + x, + y, + Math.floor(width - REACT_PRIORITY_BORDER_SIZE), + Math.floor(FLAMECHART_FRAME_HEIGHT - REACT_PRIORITY_BORDER_SIZE) + ); + + if (width > FLAMECHART_TEXT_PADDING * 2) { + const trimmedName = trimFlamegraphText( + context, + name, + width - FLAMECHART_TEXT_PADDING * 2 + (x < 0 ? x : 0) + ); + if (trimmedName !== null) { + context.fillStyle = COLORS.PRIORITY_LABEL; + context.fillText( + trimmedName, + x + FLAMECHART_TEXT_PADDING - (x < 0 ? x : 0), + y + FLAMECHART_FRAME_HEIGHT / 2 + ); + } + } + } + } + } + + // LEFT: Priority labels + // Priority labels do not scroll off screen; they are always rendered at a fixed horizontal position. + // Render them last, on top of everything else, to account for things scrolled beneath them. + y = HEADER_HEIGHT_FIXED - offsetY; + + REACT_PRIORITIES.forEach((priority, priorityIndex) => { + const priorityHeight = getPriorityHeight(data, priority); + + if (priorityHeight === 0) { + return; + } + + context.fillStyle = COLORS.PRIORITY_BACKGROUND; + context.fillRect( + 0, + Math.floor(y), + Math.floor(LABEL_FIXED_WIDTH), + priorityHeight + ); + + context.fillStyle = COLORS.PRIORITY_BORDER; + context.fillRect( + 0, + Math.floor(y + priorityHeight), + canvasWidth, + REACT_PRIORITY_BORDER_SIZE + ); + + context.fillStyle = COLORS.PRIORITY_BORDER; + context.fillRect( + Math.floor(LABEL_FIXED_WIDTH) - REACT_PRIORITY_BORDER_SIZE, + Math.floor(y), + REACT_PRIORITY_BORDER_SIZE, + priorityHeight + ); + + context.fillStyle = COLORS.PRIORITY_LABEL; + context.textAlign = 'left'; + context.textBaseline = 'middle'; + context.font = `${LABEL_FONT_SIZE}px sans-serif`; + context.fillText(priority, 4, y + priorityHeight / 2); + + y += priorityHeight + REACT_PRIORITY_BORDER_SIZE; + }); + + // TOP: Time markers + // Time markers do not scroll off screen; they are always rendered at a fixed vertical position. + // Render them last, on top of everything else, to account for things scrolled beneath them. + y = 0; + + context.fillStyle = COLORS.BACKGROUND; + context.fillRect(0, 0, canvasWidth, HEADER_HEIGHT_FIXED); + + context.fillStyle = COLORS.PRIORITY_BORDER; + context.fillRect(0, MARKER_HEIGHT, canvasWidth, REACT_PRIORITY_BORDER_SIZE); + + // Draw time marker text on top of the priority groupings + for ( + let i = firstIntervalPosition; + i < scrollableCanvasWidth; + i += intervalSize + ) { + if (i > 0) { + const markerTimestamp = positionToTimestamp( + i + LABEL_FIXED_WIDTH, + state + ); + const markerLabel = Math.round(markerTimestamp); + + const x = LABEL_FIXED_WIDTH + i; + + context.fillStyle = COLORS.PRIORITY_BORDER; + context.fillRect( + x, + MARKER_HEIGHT - MARKER_TICK_HEIGHT, + REACT_PRIORITY_BORDER_SIZE, + MARKER_TICK_HEIGHT + ); + + context.fillStyle = COLORS.TIME_MARKER_LABEL; + context.textAlign = 'right'; + context.textBaseline = 'middle'; + context.font = `${MARKER_FONT_SIZE}px sans-serif`; + context.fillText( + `${markerLabel}ms`, + x - MARKER_TEXT_PADDING, + MARKER_HEIGHT / 2 + ); + } + } + } +); diff --git a/src/canvasUtils.js b/src/canvasUtils.js deleted file mode 100644 index ddaba9a3bf140..0000000000000 --- a/src/canvasUtils.js +++ /dev/null @@ -1,48 +0,0 @@ -// @flow - -import memoize from 'memoize-one'; - -// hidpi canvas: https://www.html5rocks.com/en/tutorials/canvas/hidpi/ -export function configureRetinaCanvas( - canvas: HTMLCanvasElement, - height: number, - width: number -): number { - const dpr: number = window.devicePixelRatio || 1; - canvas.width = width * dpr; - canvas.height = height * dpr; - canvas.style.width = `${width}px`; - canvas.style.height = `${height}px`; - return dpr; -} - -export const getCanvasContext = memoize( - ( - canvas: HTMLCanvasElement, - height: number, - width: number, - scaleCanvas: boolean = true - ): CanvasRenderingContext2D => { - const context = canvas.getContext('2d', { alpha: false }); - if (scaleCanvas) { - const dpr = configureRetinaCanvas(canvas, height, width); - // Scale all drawing operations by the dpr, so you don't have to worry about the difference. - context.scale(dpr, dpr); - } - return context; - } -); - -export function getCanvasMousePos( - canvas: HTMLCanvasElement, - mouseEvent: MouseEvent -) { - const rect = - canvas instanceof HTMLCanvasElement - ? canvas.getBoundingClientRect() - : { left: 0, top: 0 }; - const canvasMouseX = mouseEvent.clientX - rect.left; - const canvasMouseY = mouseEvent.clientY - rect.top; - - return { canvasMouseX, canvasMouseY }; -} diff --git a/src/tracerbench/trace/index.js b/src/tracerbench/trace/index.js index 13724dd8a6056..3f291ed1dc780 100644 --- a/src/tracerbench/trace/index.js +++ b/src/tracerbench/trace/index.js @@ -8,4 +8,3 @@ export { loadTrace } from './load_trace'; export { liveTrace } from './live_trace'; export { networkConditions, IConditions, INetworkConditions, } from './conditions'; export * from './trace_event'; -export { getBrowserArgs } from './utils'; diff --git a/src/utils.js b/src/util/getBatchRange.js similarity index 100% rename from src/utils.js rename to src/util/getBatchRange.js diff --git a/src/preprocessData.js b/src/util/preprocessData.js similarity index 100% rename from src/preprocessData.js rename to src/util/preprocessData.js diff --git a/src/preprocessFlamechart.js b/src/util/preprocessFlamechart.js similarity index 83% rename from src/preprocessFlamechart.js rename to src/util/preprocessFlamechart.js index 87e81533a3f8d..a2ee28348fb9e 100644 --- a/src/preprocessFlamechart.js +++ b/src/util/preprocessFlamechart.js @@ -1,7 +1,7 @@ // @flow -import { importFromChromeTimeline } from './speedscope/import/chrome'; -import { Flamechart } from './speedscope/lib/flamechart'; +import { importFromChromeTimeline } from '../speedscope/import/chrome'; +import { Flamechart } from '../speedscope/lib/flamechart'; import type { TimelineEvent } from './speedscope/import/chrome'; import type { FlamechartData } from './types'; diff --git a/src/useInteractiveEvents.js b/src/util/useInteractiveEvents.js similarity index 98% rename from src/useInteractiveEvents.js rename to src/util/useInteractiveEvents.js index 65680565b539e..2e163f0be735c 100644 --- a/src/useInteractiveEvents.js +++ b/src/util/useInteractiveEvents.js @@ -2,7 +2,7 @@ import { useEffect, useRef, useState } from 'react'; import { durationToWidth, timestampToPosition } from './usePanAndZoom'; -import { EVENT_SIZE } from './constants'; +import { EVENT_SIZE } from '../constants'; function doesEventIntersectPosition(position, state, event) { const { duration, timestamp } = event; diff --git a/src/usePanAndZoom.js b/src/util/usePanAndZoom.js similarity index 99% rename from src/usePanAndZoom.js rename to src/util/usePanAndZoom.js index fa9097c6dcbb3..88d5e3a71df19 100644 --- a/src/usePanAndZoom.js +++ b/src/util/usePanAndZoom.js @@ -1,7 +1,7 @@ // @flow import { useEffect, useReducer } from 'react'; -import { getCanvasMousePos } from './canvasUtils'; +import { getCanvasMousePos } from '../canvas/canvasUtils'; import { BAR_HORIZONTAL_SPACING, MAX_ZOOM_LEVEL, @@ -9,7 +9,7 @@ import { MIN_ZOOM_LEVEL, MOVE_WHEEL_DELTA_THRESHOLD, ZOOM_WHEEL_DELTA_THRESHOLD, -} from './constants'; +} from '../canvas/constants'; export type PanAndZoomState = {| canvasHeight: number, diff --git a/src/useSmartTooltip.js b/src/util/useSmartTooltip.js similarity index 100% rename from src/useSmartTooltip.js rename to src/util/useSmartTooltip.js From dab97b0aec3b5badca96ec4847660da93091c553 Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Tue, 23 Jun 2020 19:45:52 +0800 Subject: [PATCH 018/116] Add types for canvas files --- src/App.js | 11 ++--------- src/canvas/canvasUtils.js | 16 ++++++++++++++-- src/canvas/renderCanvas.js | 9 +++++++-- 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/src/App.js b/src/App.js index 35d1a8c385a83..fb56ea65e6cac 100644 --- a/src/App.js +++ b/src/App.js @@ -15,15 +15,8 @@ import { unstable_batchedUpdates } from 'react-dom'; import memoize from 'memoize-one'; import usePanAndZoom from './util/usePanAndZoom'; -import { - getCanvasContext, - getTimeTickInterval, - cachedFlamegraphTextWidths, - trimFlamegraphText, - getHoveredEvent, - getPriorityHeight, -} from './canvas/canvasUtils'; -import { renderCanvas, renderReact } from './canvas/renderCanvas'; +import { getHoveredEvent, getPriorityHeight } from './canvas/canvasUtils'; +import { renderCanvas } from './canvas/renderCanvas'; import prettyMilliseconds from 'pretty-ms'; import { getBatchRange } from './util/getBatchRange'; diff --git a/src/canvas/canvasUtils.js b/src/canvas/canvasUtils.js index 970365ef865a9..7ca6c4f5a8f7f 100644 --- a/src/canvas/canvasUtils.js +++ b/src/canvas/canvasUtils.js @@ -1,6 +1,14 @@ // @flow // Contains helper functions for rendering canvas elements +import type { + ReactProfilerData, + FlamechartData, + ReactHoverContextInfo, + ReactPriority, +} from '../types'; +import type { PanAndZoomState } from '../util/usePanAndZoom'; + import memoize from 'memoize-one'; import { INTERVAL_TIMES, @@ -69,7 +77,7 @@ export function getCanvasMousePos( // In Chrome, these seem to range from 70-140 pixels wide. // Time wise, they represent intervals of e.g. 1s, 500ms, 200ms, 100ms, 50ms, 20ms. // Based on zoom, we should determine which amount to actually show. -export function getTimeTickInterval(zoomLevel) { +export function getTimeTickInterval(zoomLevel: number) { let interval = INTERVAL_TIMES[0]; for (let i = 0; i < INTERVAL_TIMES.length; i++) { const currentInterval = INTERVAL_TIMES[i]; @@ -82,7 +90,11 @@ export function getTimeTickInterval(zoomLevel) { } export const cachedFlamegraphTextWidths = new Map(); -export const trimFlamegraphText = (context, text, width) => { +export const trimFlamegraphText = ( + context: CanvasRenderingContext2D, + text: string, + width: number +) => { for (let i = text.length - 1; i >= 0; i--) { const trimmedText = i === text.length - 1 ? text : text.substr(0, i) + '…'; diff --git a/src/canvas/renderCanvas.js b/src/canvas/renderCanvas.js index 379206f78cca3..7022860760941 100644 --- a/src/canvas/renderCanvas.js +++ b/src/canvas/renderCanvas.js @@ -1,5 +1,12 @@ // @flow +import type { + ReactProfilerData, + FlamechartData, + ReactHoverContextInfo, +} from '../types'; +import type { PanAndZoomState } from '../util/usePanAndZoom'; + import React from 'react'; import memoize from 'memoize-one'; @@ -37,8 +44,6 @@ import { HEADER_HEIGHT_FIXED, } from './constants'; -import type { PanAndZoomState } from '../util/usePanAndZoom'; - // The canvas we're rendering looks a little like the outline below. // Left labels mark different scheduler REACT_PRIORITIES, // and top labels mark different times (based on how long the data runs and how zoomed in we are). From 363c2588e45d29431619fd04c0b820f4ebda63e3 Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Fri, 26 Jun 2020 14:36:14 +0800 Subject: [PATCH 019/116] Use React project Prettier configs (#21) * Upgrade Prettier * Copy React's Prettier config * Customize prettier config to allow CSS/JSON prettifying and ignore folders * yarn prettier * Downgrade to Prettier 1.19.1 and run prettier --- .prettierignore | 4 ++- .prettierrc | 7 ++-- package.json | 2 +- src/App.js | 58 ++++++++++++++------------------ src/EventTooltip.js | 35 +++++++++---------- src/canvas/canvasUtils.js | 32 +++++++++--------- src/canvas/renderCanvas.js | 42 +++++++++++------------ src/context/ContextMenu.js | 14 ++++---- src/context/ContextMenuItem.js | 11 +++--- src/context/Contexts.js | 6 ++-- src/context/index.js | 4 +-- src/context/useContextMenu.js | 14 ++++---- src/graveyard/SelectedEvent.js | 6 ++-- src/graveyard/contexts.js | 2 +- src/graveyard/useDebounce.js | 4 +-- src/index.js | 4 +-- src/serviceWorker.js | 10 +++--- src/types.js | 2 +- src/util/getBatchRange.js | 4 +-- src/util/preprocessData.js | 56 +++++++++++++++--------------- src/util/preprocessFlamechart.js | 10 +++--- src/util/useInteractiveEvents.js | 10 +++--- src/util/usePanAndZoom.js | 50 +++++++++++++-------------- src/util/useSmartTooltip.js | 2 +- yarn.lock | 2 +- 25 files changed, 193 insertions(+), 198 deletions(-) diff --git a/.prettierignore b/.prettierignore index bd3947a216a21..a8c23db6dc580 100644 --- a/.prettierignore +++ b/.prettierignore @@ -5,4 +5,6 @@ node_modules/* dist/* static/* src/speedscope/* -src/tracerbench/* \ No newline at end of file +src/tracerbench/* +coverage +.vscode diff --git a/.prettierrc b/.prettierrc index 1502887d63fd9..c3740a0238032 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,4 +1,7 @@ { + "bracketSpacing": false, "singleQuote": true, - "trailingComma": "es5" -} \ No newline at end of file + "jsxBracketSameLine": true, + "printWidth": 80, + "trailingComma": "all" +} diff --git a/package.json b/package.json index 02b824682a713..61c4fa8c3a432 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,6 @@ "jest": "^26.0.1", "parcel": "2.0.0-alpha.3.2", "postcss-modules": "^2.0.0", - "prettier": "^1.19.1" + "prettier": "1.19.1" } } diff --git a/src/App.js b/src/App.js index fb56ea65e6cac..9934e66ff969e 100644 --- a/src/App.js +++ b/src/App.js @@ -1,9 +1,9 @@ // @flow -import type { TimelineEvent } from './speedscope/import/chrome'; -import type { PanAndZoomState } from './util/usePanAndZoom'; +import type {TimelineEvent} from './speedscope/import/chrome'; +import type {PanAndZoomState} from './util/usePanAndZoom'; -import { copy } from 'clipboard-js'; +import {copy} from 'clipboard-js'; import React, { Fragment, useEffect, @@ -11,15 +11,15 @@ import React, { useRef, useState, } from 'react'; -import { unstable_batchedUpdates } from 'react-dom'; +import {unstable_batchedUpdates} from 'react-dom'; import memoize from 'memoize-one'; import usePanAndZoom from './util/usePanAndZoom'; -import { getHoveredEvent, getPriorityHeight } from './canvas/canvasUtils'; -import { renderCanvas } from './canvas/renderCanvas'; +import {getHoveredEvent, getPriorityHeight} from './canvas/canvasUtils'; +import {renderCanvas} from './canvas/renderCanvas'; import prettyMilliseconds from 'pretty-ms'; -import { getBatchRange } from './util/getBatchRange'; +import {getBatchRange} from './util/getBatchRange'; import EventTooltip from './EventTooltip'; import preprocessData from './util/preprocessData'; import preprocessFlamechart from './util/preprocessFlamechart'; @@ -33,7 +33,7 @@ import { HEADER_HEIGHT_FIXED, } from './canvas/constants'; -import { ContextMenu, ContextMenuItem, useContextMenu } from './context'; +import {ContextMenu, ContextMenuItem, useContextMenu} from './context'; // TODO: Add import button but keep a static path until canvas layout is ready import JSON_PATH from 'url:../static/small-devtools.json'; @@ -91,9 +91,9 @@ function App() { }, []); return ( -
+
- {({ height, width }: { height: number, width: number }) => ( + {({height, width}: {height: number, width: number}) => ( { - const { batchUID, duration, priority, timestamp, type } = measure; + const {batchUID, duration, priority, timestamp, type} = measure; const [startTime, stopTime] = getBatchRange(batchUID, priority, data); @@ -118,20 +118,20 @@ const copySummary = (data: ReactProfilerData | null, measure: ReactMeasure) => { timestamp: prettyMilliseconds(timestamp), duration: prettyMilliseconds(duration), batchDuration: prettyMilliseconds(stopTime - startTime), - }) + }), ); }; const zoomToBatch = ( data: ReactProfilerData | null, measure: ReactMeasure, - state: PanAndZoomState + state: PanAndZoomState, ) => { - const { zoomTo } = state; + const {zoomTo} = state; if (!data || !zoomTo) { return; } - const { batchUID, priority } = measure; + const {batchUID, priority} = measure; const [startTime, stopTime] = getBatchRange(batchUID, priority, data); zoomTo(startTime, stopTime); }; @@ -171,7 +171,7 @@ function AutoSizedCanvas({ schedulerCanvasHeight, data, flamechart, - state + state, ); const [isContextMenuShown, setIsContextMenuShown] = useState(false); @@ -197,7 +197,7 @@ function AutoSizedCanvas({ height, schedulerCanvasHeight, state, - hoveredEvent + hoveredEvent, ); } }); @@ -211,50 +211,45 @@ function AutoSizedCanvas({ width={width} /> - {({ data, hoveredEvent }: ContextMenuContextData) => { + {({data, hoveredEvent}: ContextMenuContextData) => { if (hoveredEvent == null) { return null; } - const { event, flamechartNode, measure } = hoveredEvent; + const {event, flamechartNode, measure} = hoveredEvent; return ( {event !== null && ( copy(event.componentName)} - title="Copy component name" - > + title="Copy component name"> Copy component name )} {event !== null && ( copy(event.componentStack)} - title="Copy component stack" - > + title="Copy component stack"> Copy component stack )} {measure !== null && ( zoomToBatch(data, measure, state)} - title="Zoom to batch" - > + title="Zoom to batch"> Zoom to batch )} {measure !== null && ( copySummary(data, measure)} - title="Copy summary" - > + title="Copy summary"> Copy summary )} {flamechartNode !== null && ( copy(flamechartNode.node.frame.file)} - title="Copy file path" - > + title="Copy file path"> Copy file path )} @@ -262,11 +257,10 @@ function AutoSizedCanvas({ copy( - `line ${flamechartNode.node.frame.line}, column ${flamechartNode.node.frame.col}` + `line ${flamechartNode.node.frame.line}, column ${flamechartNode.node.frame.col}`, ) } - title="Copy location" - > + title="Copy location"> Copy location )} diff --git a/src/EventTooltip.js b/src/EventTooltip.js index 39446faef8b59..1210e8177729d 100644 --- a/src/EventTooltip.js +++ b/src/EventTooltip.js @@ -1,7 +1,7 @@ // @flow -import type { PanAndZoomState } from './util/usePanAndZoom'; -import type { FlamechartFrame } from './speedscope/lib/flamechart'; +import type {PanAndZoomState} from './util/usePanAndZoom'; +import type {FlamechartFrame} from './speedscope/lib/flamechart'; import type { ReactEvent, ReactMeasure, @@ -11,9 +11,9 @@ import type { } from './types'; import prettyMilliseconds from 'pretty-ms'; -import React, { Fragment, useLayoutEffect, useRef } from 'react'; -import { COLORS } from './canvas/constants'; -import { getBatchRange } from './util/getBatchRange'; +import React, {Fragment, useLayoutEffect, useRef} from 'react'; +import {COLORS} from './canvas/constants'; +import {getBatchRange} from './util/getBatchRange'; import useSmartTooltip from './util/useSmartTooltip'; import styles from './EventTooltip.css'; @@ -25,8 +25,8 @@ type Props = {| state: PanAndZoomState, |}; -export default function EventTooltip({ data, hoveredEvent, state }: Props) { - const { canvasMouseY, canvasMouseX } = state; +export default function EventTooltip({data, hoveredEvent, state}: Props) { + const {canvasMouseY, canvasMouseX} = state; const tooltipRef = useSmartTooltip({ mouseX: canvasMouseX, @@ -37,7 +37,7 @@ export default function EventTooltip({ data, hoveredEvent, state }: Props) { return null; } - const { event, flamechartNode, measure } = hoveredEvent; + const {event, flamechartNode, measure} = hoveredEvent; if (event !== null) { switch (event.type) { @@ -130,8 +130,8 @@ const TooltipFlamechartNode = ({ flamechartNode: FlamechartFrame, tooltipRef: Return, }) => { - const { end, node, start } = flamechartNode; - const { col, file, line, name } = node.frame; + const {end, node, start} = flamechartNode; + const {col, file, line, name} = node.frame; return (
+ ref={tooltipRef}> {prettyMilliseconds((end - start) / 1000)} {name}
Script URL:
{file} @@ -162,7 +161,7 @@ const TooltipReactEvent = ({ event: ReactEvent, tooltipRef: Return, }) => { - const { componentName, componentStack, timestamp, type } = event; + const {componentName, componentStack, timestamp, type} = event; let label = null; switch (type) { @@ -186,10 +185,9 @@ const TooltipReactEvent = ({ backgroundColor: COLORS.TOOLTIP_BG, color: COLORS.TOOLTIP, }} - ref={tooltipRef} - > + ref={tooltipRef}> {componentName && ( - + {componentName} )}{' '} @@ -220,7 +218,7 @@ const TooltipReactMeasure = ({ measure: ReactMeasure, tooltipRef: Return, }) => { - const { batchUID, duration, priority, timestamp, type } = measure; + const {batchUID, duration, priority, timestamp, type} = measure; let label = null; switch (type) { @@ -253,8 +251,7 @@ const TooltipReactMeasure = ({ backgroundColor: COLORS.TOOLTIP_BG, color: COLORS.TOOLTIP, }} - ref={tooltipRef} - > + ref={tooltipRef}> {prettyMilliseconds(duration)} {label}
diff --git a/src/canvas/canvasUtils.js b/src/canvas/canvasUtils.js index 7ca6c4f5a8f7f..7faf511b8e470 100644 --- a/src/canvas/canvasUtils.js +++ b/src/canvas/canvasUtils.js @@ -7,7 +7,7 @@ import type { ReactHoverContextInfo, ReactPriority, } from '../types'; -import type { PanAndZoomState } from '../util/usePanAndZoom'; +import type {PanAndZoomState} from '../util/usePanAndZoom'; import memoize from 'memoize-one'; import { @@ -32,7 +32,7 @@ import usePanAndZoom, { export function configureRetinaCanvas( canvas: HTMLCanvasElement, height: number, - width: number + width: number, ): number { const dpr: number = window.devicePixelRatio || 1; canvas.width = width * dpr; @@ -47,30 +47,30 @@ export const getCanvasContext = memoize( canvas: HTMLCanvasElement, height: number, width: number, - scaleCanvas: boolean = true + scaleCanvas: boolean = true, ): CanvasRenderingContext2D => { - const context = canvas.getContext('2d', { alpha: false }); + const context = canvas.getContext('2d', {alpha: false}); if (scaleCanvas) { const dpr = configureRetinaCanvas(canvas, height, width); // Scale all drawing operations by the dpr, so you don't have to worry about the difference. context.scale(dpr, dpr); } return context; - } + }, ); export function getCanvasMousePos( canvas: HTMLCanvasElement, - mouseEvent: MouseEvent + mouseEvent: MouseEvent, ) { const rect = canvas instanceof HTMLCanvasElement ? canvas.getBoundingClientRect() - : { left: 0, top: 0 }; + : {left: 0, top: 0}; const canvasMouseX = mouseEvent.clientX - rect.left; const canvasMouseY = mouseEvent.clientY - rect.top; - return { canvasMouseX, canvasMouseY }; + return {canvasMouseX, canvasMouseY}; } // Time mark intervals vary based on the current zoom range and the time it represents. @@ -93,7 +93,7 @@ export const cachedFlamegraphTextWidths = new Map(); export const trimFlamegraphText = ( context: CanvasRenderingContext2D, text: string, - width: number + width: number, ) => { for (let i = text.length - 1; i >= 0; i--) { const trimmedText = i === text.length - 1 ? text : text.substr(0, i) + '…'; @@ -116,9 +116,9 @@ export function getHoveredEvent( schedulerCanvasHeight: number, data: ReactProfilerData | null, flamechart: FlamechartData | null, - state: PanAndZoomState + state: PanAndZoomState, ): ReactHoverContextInfo | null { - const { canvasMouseX, canvasMouseY, offsetY } = state; + const {canvasMouseX, canvasMouseY, offsetY} = state; if (canvasMouseX < LABEL_FIXED_WIDTH || canvasMouseY < HEADER_HEIGHT_FIXED) { return null; @@ -165,7 +165,7 @@ export function getHoveredEvent( if (events !== null) { for (let index = events.length - 1; index >= 0; index--) { const event = events[index]; - const { timestamp } = event; + const {timestamp} = event; const eventX = timestampToPosition(timestamp, state); const startX = eventX - REACT_EVENT_SIZE / 2; @@ -185,7 +185,7 @@ export function getHoveredEvent( // This will always be the one on "top" (the one the user is hovering over). for (let index = measures.length - 1; index >= 0; index--) { const measure = measures[index]; - const { duration, timestamp } = measure; + const {duration, timestamp} = measure; const pointerTime = positionToTimestamp(canvasMouseX, state); @@ -205,7 +205,7 @@ export function getHoveredEvent( if (flamechart !== null) { const layerIndex = Math.floor( (canvasMouseY + offsetY - HEADER_HEIGHT_FIXED - schedulerCanvasHeight) / - FLAMECHART_FRAME_HEIGHT + FLAMECHART_FRAME_HEIGHT, ); const layer = flamechart.layers[layerIndex]; @@ -216,7 +216,7 @@ export function getHoveredEvent( const currentIndex = Math.floor((startIndex + stopIndex) / 2); const flamechartNode = layer[currentIndex]; - const { end, start } = flamechartNode; + const {end, start} = flamechartNode; const width = durationToWidth((end - start) / 1000, state); const x = Math.floor(timestampToPosition(start / 1000, state)); @@ -247,7 +247,7 @@ export function getHoveredEvent( const cachedPriorityHeights = new Map(); export const getPriorityHeight = ( data: ReactProfilerData, - priority: ReactPriority + priority: ReactPriority, ): number => { if (cachedPriorityHeights.has(priority)) { // We know the value must be present because we've just checked. diff --git a/src/canvas/renderCanvas.js b/src/canvas/renderCanvas.js index 7022860760941..06de2c3a35c91 100644 --- a/src/canvas/renderCanvas.js +++ b/src/canvas/renderCanvas.js @@ -5,7 +5,7 @@ import type { FlamechartData, ReactHoverContextInfo, } from '../types'; -import type { PanAndZoomState } from '../util/usePanAndZoom'; +import type {PanAndZoomState} from '../util/usePanAndZoom'; import React from 'react'; import memoize from 'memoize-one'; @@ -89,8 +89,8 @@ export const renderReact = ({ showHoverHighlight, state, }) => { - const { timestamp, type } = eventOrMeasure; - const { offsetY } = state; + const {timestamp, type} = eventOrMeasure; + const {offsetY} = state; let fillStyle = null; let hoveredFillStyle = null; @@ -103,7 +103,7 @@ export const renderReact = ({ case 'render': case 'layout-effects': case 'passive-effects': - const { depth, duration } = ((eventOrMeasure: any): ReactMeasure); + const {depth, duration} = ((eventOrMeasure: any): ReactMeasure); // We could change the max to 0 and just skip over rendering anything that small, // but this has the effect of making the chart look very empty when zoomed out. @@ -166,13 +166,13 @@ export const renderReact = ({ Math.floor(x), Math.floor(y), Math.floor(width), - REACT_WORK_SIZE + REACT_WORK_SIZE, ); break; case 'schedule-render': case 'schedule-state-update': case 'suspend': - const { isCascading } = ((eventOrMeasure: any): ReactEvent); + const {isCascading} = ((eventOrMeasure: any): ReactEvent); x = timestampToPosition(timestamp, state); if (x + EVENT_SIZE / 2 < 0 || canvasWidth < x) { @@ -228,9 +228,9 @@ export const renderCanvas = memoize( canvasHeight: number, schedulerCanvasHeight: number, state: PanAndZoomState, - hoveredEvent: ReactHoverContextInfo | null + hoveredEvent: ReactHoverContextInfo | null, ) => { - const { offsetX, offsetY, zoomLevel } = state; + const {offsetX, offsetY, zoomLevel} = state; const context = getCanvasContext(canvas, canvasHeight, canvasWidth, true); @@ -333,7 +333,7 @@ export const renderCanvas = memoize( HEADER_HEIGHT_FIXED + schedulerCanvasHeight + i * FLAMECHART_FRAME_HEIGHT - - offsetY + offsetY, ); if ( y + FLAMECHART_FRAME_HEIGHT < HEADER_HEIGHT_FIXED || @@ -343,8 +343,8 @@ export const renderCanvas = memoize( } for (let j = 0; j < nodes.length; j++) { - const { end, node, start } = nodes[j]; - const { name } = node.frame; + const {end, node, start} = nodes[j]; + const {name} = node.frame; let showHoverHighlight = hoveredEvent && hoveredEvent.flamechartNode === nodes[j]; @@ -367,21 +367,21 @@ export const renderCanvas = memoize( x, y, Math.floor(width - REACT_PRIORITY_BORDER_SIZE), - Math.floor(FLAMECHART_FRAME_HEIGHT - REACT_PRIORITY_BORDER_SIZE) + Math.floor(FLAMECHART_FRAME_HEIGHT - REACT_PRIORITY_BORDER_SIZE), ); if (width > FLAMECHART_TEXT_PADDING * 2) { const trimmedName = trimFlamegraphText( context, name, - width - FLAMECHART_TEXT_PADDING * 2 + (x < 0 ? x : 0) + width - FLAMECHART_TEXT_PADDING * 2 + (x < 0 ? x : 0), ); if (trimmedName !== null) { context.fillStyle = COLORS.PRIORITY_LABEL; context.fillText( trimmedName, x + FLAMECHART_TEXT_PADDING - (x < 0 ? x : 0), - y + FLAMECHART_FRAME_HEIGHT / 2 + y + FLAMECHART_FRAME_HEIGHT / 2, ); } } @@ -406,7 +406,7 @@ export const renderCanvas = memoize( 0, Math.floor(y), Math.floor(LABEL_FIXED_WIDTH), - priorityHeight + priorityHeight, ); context.fillStyle = COLORS.PRIORITY_BORDER; @@ -414,7 +414,7 @@ export const renderCanvas = memoize( 0, Math.floor(y + priorityHeight), canvasWidth, - REACT_PRIORITY_BORDER_SIZE + REACT_PRIORITY_BORDER_SIZE, ); context.fillStyle = COLORS.PRIORITY_BORDER; @@ -422,7 +422,7 @@ export const renderCanvas = memoize( Math.floor(LABEL_FIXED_WIDTH) - REACT_PRIORITY_BORDER_SIZE, Math.floor(y), REACT_PRIORITY_BORDER_SIZE, - priorityHeight + priorityHeight, ); context.fillStyle = COLORS.PRIORITY_LABEL; @@ -454,7 +454,7 @@ export const renderCanvas = memoize( if (i > 0) { const markerTimestamp = positionToTimestamp( i + LABEL_FIXED_WIDTH, - state + state, ); const markerLabel = Math.round(markerTimestamp); @@ -465,7 +465,7 @@ export const renderCanvas = memoize( x, MARKER_HEIGHT - MARKER_TICK_HEIGHT, REACT_PRIORITY_BORDER_SIZE, - MARKER_TICK_HEIGHT + MARKER_TICK_HEIGHT, ); context.fillStyle = COLORS.TIME_MARKER_LABEL; @@ -475,9 +475,9 @@ export const renderCanvas = memoize( context.fillText( `${markerLabel}ms`, x - MARKER_TEXT_PADDING, - MARKER_HEIGHT / 2 + MARKER_HEIGHT / 2, ); } } - } + }, ); diff --git a/src/context/ContextMenu.js b/src/context/ContextMenu.js index 72c64f42e1d9c..bc678c141af25 100644 --- a/src/context/ContextMenu.js +++ b/src/context/ContextMenu.js @@ -7,8 +7,8 @@ import React, { useRef, useState, } from 'react'; -import { createPortal } from 'react-dom'; -import { RegistryContext } from './Contexts'; +import {createPortal} from 'react-dom'; +import {RegistryContext} from './Contexts'; import styles from './ContextMenu.css'; @@ -49,8 +49,8 @@ type Props = {| id: string, |}; -export default function ContextMenu({ children, id }: Props) { - const { hideMenu, registerMenu } = useContext(RegistryContext); +export default function ContextMenu({children, id}: Props) { + const {hideMenu, registerMenu} = useContext(RegistryContext); const [state, setState] = useState(HIDDEN_STATE); @@ -75,8 +75,8 @@ export default function ContextMenu({ children, id }: Props) { }, [bodyAccessorRef, containerRef]); useEffect(() => { - const showMenu = ({ data, pageX, pageY }) => { - setState({ data, isVisible: true, pageX, pageY }); + const showMenu = ({data, pageX, pageY}) => { + setState({data, isVisible: true, pageX, pageY}); }; const hideMenu = () => setState(HIDDEN_STATE); return registerMenu(id, showMenu, hideMenu); @@ -126,7 +126,7 @@ export default function ContextMenu({ children, id }: Props) {
{children(state.data)}
, - containerRef.current + containerRef.current, ); } } diff --git a/src/context/ContextMenuItem.js b/src/context/ContextMenuItem.js index 20a89f7e4ab66..09029e9553e5b 100644 --- a/src/context/ContextMenuItem.js +++ b/src/context/ContextMenuItem.js @@ -1,7 +1,7 @@ // @flow -import React, { useContext } from 'react'; -import { RegistryContext } from './Contexts'; +import React, {useContext} from 'react'; +import {RegistryContext} from './Contexts'; import styles from './ContextMenuItem.css'; @@ -11,8 +11,8 @@ type Props = {| title: string, |}; -export default function ContextMenuItem({ children, onClick, title }: Props) { - const { hideMenu } = useContext(RegistryContext); +export default function ContextMenuItem({children, onClick, title}: Props) { + const {hideMenu} = useContext(RegistryContext); const handleClick: MouseEventHandler = event => { onClick(); @@ -23,8 +23,7 @@ export default function ContextMenuItem({ children, onClick, title }: Props) {
+ onTouchEnd={handleClick}> {children}
); diff --git a/src/context/Contexts.js b/src/context/Contexts.js index 43618402da777..a59d0282b75ff 100644 --- a/src/context/Contexts.js +++ b/src/context/Contexts.js @@ -1,8 +1,8 @@ // @flow -import { createContext } from 'react'; +import {createContext} from 'react'; -export type ShowFn = ({| data: Object, pageX: number, pageY: number |}) => void; +export type ShowFn = ({|data: Object, pageX: number, pageY: number|}) => void; export type HideFn = () => void; export type OnChangeFn = boolean => void; @@ -41,7 +41,7 @@ function showMenu({ const showFn = idToShowFnMap.get(id); if (typeof showFn === 'function') { currentHideFn = idToHideFnMap.get(id); - showFn({ data, pageX, pageY }); + showFn({data, pageX, pageY}); if (typeof onChange === 'function') { currentOnChange = onChange; diff --git a/src/context/index.js b/src/context/index.js index 6693b126ca75d..60aa333642d7b 100644 --- a/src/context/index.js +++ b/src/context/index.js @@ -1,8 +1,8 @@ // @flow -import { RegistryContext } from './Contexts'; +import {RegistryContext} from './Contexts'; import ContextMenu from './ContextMenu'; import ContextMenuItem from './ContextMenuItem'; import useContextMenu from './useContextMenu'; -export { RegistryContext, ContextMenu, ContextMenuItem, useContextMenu }; +export {RegistryContext, ContextMenu, ContextMenuItem, useContextMenu}; diff --git a/src/context/useContextMenu.js b/src/context/useContextMenu.js index f231bde4b8934..5fcb094217446 100644 --- a/src/context/useContextMenu.js +++ b/src/context/useContextMenu.js @@ -1,11 +1,11 @@ // @flow -import { useContext, useEffect, useRef } from 'react'; -import { RegistryContext } from './Contexts'; +import {useContext, useEffect, useRef} from 'react'; +import {RegistryContext} from './Contexts'; -import type { ElementRef } from 'react'; -import type { OnChangeFn } from './Contexts'; -import type { Return } from '../types'; +import type {ElementRef} from 'react'; +import type {OnChangeFn} from './Contexts'; +import type {Return} from '../types'; export default function useContextMenu({ data, @@ -18,7 +18,7 @@ export default function useContextMenu({ onChange: OnChangeFn, ref: Return, |}) { - const { showMenu } = useContext(RegistryContext); + const {showMenu} = useContext(RegistryContext); useEffect(() => { if (ref.current !== null) { @@ -31,7 +31,7 @@ export default function useContextMenu({ const pageY: number = event.pageY || (event.touches && event.touches[0].pageY); - showMenu({ data, id, onChange, pageX, pageY }); + showMenu({data, id, onChange, pageX, pageY}); }; const trigger = ref.current; diff --git a/src/graveyard/SelectedEvent.js b/src/graveyard/SelectedEvent.js index 3843dcaeaedfd..77fd35d9fc5ae 100644 --- a/src/graveyard/SelectedEvent.js +++ b/src/graveyard/SelectedEvent.js @@ -1,12 +1,12 @@ import React from 'react'; import styles from './SelectedEvent.module.css'; -export default function SelectedEvent({ selectedEvent, width }) { +export default function SelectedEvent({selectedEvent, width}) { if (selectedEvent == null) { return null; } - const { componentStack, duration, timestamp, type } = selectedEvent; + const {componentStack, duration, timestamp, type} = selectedEvent; let label = null; switch (type) { @@ -36,7 +36,7 @@ export default function SelectedEvent({ selectedEvent, width }) { } return ( -
+
{label} {duration !== undefined ? `for ${duration}ms` : ''} at {timestamp} ms {componentStack && ( diff --git a/src/graveyard/contexts.js b/src/graveyard/contexts.js index f02f24b30cfb6..acb25e15c642e 100644 --- a/src/graveyard/contexts.js +++ b/src/graveyard/contexts.js @@ -1,6 +1,6 @@ // @flow -import { createContext } from 'react'; +import {createContext} from 'react'; export const PriorityContext = createContext(null); export const TimeRangeContext = createContext([0, 0]); diff --git a/src/graveyard/useDebounce.js b/src/graveyard/useDebounce.js index 4d1fb606f58ff..9637ba1c3bab6 100644 --- a/src/graveyard/useDebounce.js +++ b/src/graveyard/useDebounce.js @@ -1,6 +1,6 @@ // @flow -import { useDebugValue, useEffect, useState } from 'react'; +import {useDebugValue, useEffect, useState} from 'react'; // Below copied from https://usehooks.com/ export default function useDebounce(value: T, delay: number): T { @@ -24,7 +24,7 @@ export default function useDebounce(value: T, delay: number): T { clearTimeout(handler); }; }, - [value, delay] // Only re-call effect if value or delay changes + [value, delay], // Only re-call effect if value or delay changes ); return debouncedValue; diff --git a/src/index.js b/src/index.js index 0e636c9b8e253..fb86a18a32043 100644 --- a/src/index.js +++ b/src/index.js @@ -1,5 +1,5 @@ -import { createElement } from 'react'; -import { render } from 'react-dom'; +import {createElement} from 'react'; +import {render} from 'react-dom'; import App from './App'; import './index.css'; diff --git a/src/serviceWorker.js b/src/serviceWorker.js index f8c7e50c20176..4f5e7f1f2cd17 100644 --- a/src/serviceWorker.js +++ b/src/serviceWorker.js @@ -16,8 +16,8 @@ const isLocalhost = Boolean( window.location.hostname === '[::1]' || // 127.0.0.1/8 is considered localhost for IPv4. window.location.hostname.match( - /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ - ) + /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/, + ), ); export function register(config) { @@ -43,7 +43,7 @@ export function register(config) { navigator.serviceWorker.ready.then(() => { console.log( 'This web app is being served cache-first by a service ' + - 'worker. To learn more, visit https://bit.ly/CRA-PWA' + 'worker. To learn more, visit https://bit.ly/CRA-PWA', ); }); } else { @@ -71,7 +71,7 @@ function registerValidSW(swUrl, config) { // content until all client tabs are closed. console.log( 'New content is available and will be used when all ' + - 'tabs for this page are closed. See https://bit.ly/CRA-PWA.' + 'tabs for this page are closed. See https://bit.ly/CRA-PWA.', ); // Execute callback @@ -121,7 +121,7 @@ function checkValidServiceWorker(swUrl, config) { }) .catch(() => { console.log( - 'No internet connection found. App is running in offline mode.' + 'No internet connection found. App is running in offline mode.', ); }); } diff --git a/src/types.js b/src/types.js index d1c8d2077d80e..853210528b014 100644 --- a/src/types.js +++ b/src/types.js @@ -1,6 +1,6 @@ // @flow -import type { Flamechart, FlamechartFrame } from './speedscope/lib/flamechart'; +import type {Flamechart, FlamechartFrame} from './speedscope/lib/flamechart'; // Type utilities diff --git a/src/util/getBatchRange.js b/src/util/getBatchRange.js index 8105224d4a935..d17add4950ed2 100644 --- a/src/util/getBatchRange.js +++ b/src/util/getBatchRange.js @@ -15,9 +15,9 @@ import type { function unmemoizedGetBatchRange( batchUID: BatchUID, priority: ReactPriority, - data: ReactProfilerData + data: ReactProfilerData, ): [Milliseconds, Milliseconds] { - const { measures } = data[priority]; + const {measures} = data[priority]; let startTime = 0; let stopTime = Infinity; diff --git a/src/util/preprocessData.js b/src/util/preprocessData.js index 2b88d08563921..1cb58fcc3c6db 100644 --- a/src/util/preprocessData.js +++ b/src/util/preprocessData.js @@ -1,6 +1,6 @@ // @flow -import type { TimelineEvent } from './speedscope/import/chrome'; +import type {TimelineEvent} from './speedscope/import/chrome'; import type { Milliseconds, @@ -30,7 +30,7 @@ type Metadata = {| |}; export default function reactProfilerProcessor( - rawData: TimelineEvent[] + rawData: TimelineEvent[], ): ReactProfilerData { const reactProfilerData = { startTime: rawData[0].ts, @@ -62,7 +62,7 @@ export default function reactProfilerProcessor( let currentProfilerDataGroup: ReactProfilerDataPriority | null = null; let uidCounter = 0; - const metadata: {| [priority: ReactPriority]: Metadata |} = { + const metadata: {|[priority: ReactPriority]: Metadata|} = { high: { batchUID: 0, nextRenderShouldGenerateNewBatchID: true, @@ -89,9 +89,9 @@ export default function reactProfilerProcessor( if (!currentMetadata) { return null; } - const { stack } = currentMetadata; + const {stack} = currentMetadata; if (stack.length > 0) { - const { type } = stack[stack.length - 1]; + const {type} = stack[stack.length - 1]; return type; } return null; @@ -101,9 +101,9 @@ export default function reactProfilerProcessor( if (!currentMetadata) { return 0; } - const { stack } = currentMetadata; + const {stack} = currentMetadata; if (stack.length > 0) { - const { depth, type } = (stack[stack.length - 1]: StackElement); + const {depth, type} = (stack[stack.length - 1]: StackElement); return type === 'render-idle' ? depth : depth + 1; } return 0; @@ -111,30 +111,30 @@ export default function reactProfilerProcessor( const markWorkCompleted = ( type: ReactMeasureType, - stopTime: Milliseconds + stopTime: Milliseconds, ) => { if (!currentMetadata) { return; } - const { stack } = currentMetadata; + const {stack} = currentMetadata; if (stack.length === 0) { console.error( - `Unexpected type "${type}" completed while stack is empty.` + `Unexpected type "${type}" completed while stack is empty.`, ); } else { const last = stack[stack.length - 1]; if (last.type !== type) { console.error( - `Unexpected type "${type}" completed before "${last.type}" completed.` + `Unexpected type "${type}" completed before "${last.type}" completed.`, ); } else { - const { index, startTime } = stack.pop(); + const {index, startTime} = stack.pop(); if (currentProfilerDataGroup) { const measure = currentProfilerDataGroup.measures[index]; if (!measure) { console.error( - `Could not find matching measure for type "${type}".` + `Could not find matching measure for type "${type}".`, ); } else { // $FlowFixMe This property should not be writable outside of this function. @@ -149,14 +149,14 @@ export default function reactProfilerProcessor( if (!currentMetadata || !currentProfilerDataGroup) { return; } - const { batchUID, stack } = currentMetadata; + const {batchUID, stack} = currentMetadata; const index = currentProfilerDataGroup.measures.length; const depth = getDepth(); currentProfilerDataGroup.maxNestedMeasures = Math.max( currentProfilerDataGroup.maxNestedMeasures, - depth + 1 + depth + 1, ); stack.push({ @@ -180,13 +180,13 @@ export default function reactProfilerProcessor( if (!currentMetadata) { return; } - const { stack } = currentMetadata; + const {stack} = currentMetadata; const lastIndex = stack.length - 1; if (lastIndex >= 0) { const last = stack[lastIndex]; if (last.stopTime === undefined && last.type === type) { throw new Error( - `Unexpected type "${type}" started before "${last.type}" completed.` + `Unexpected type "${type}" started before "${last.type}" completed.`, ); } } @@ -195,7 +195,7 @@ export default function reactProfilerProcessor( for (let i = 0; i < rawData.length; i++) { const currentEvent = rawData[i]; - const { cat, name, ts } = currentEvent; + const {cat, name, ts} = currentEvent; if (cat !== 'blink.user_timing' || !name.startsWith('--')) { continue; @@ -217,7 +217,7 @@ export default function reactProfilerProcessor( if (name.startsWith('--scheduler-start-')) { if (currentPriority !== 'unscheduled') { console.error( - `Unexpected scheduler start: "${name}" with current priority: "${currentPriority}"` + `Unexpected scheduler start: "${name}" with current priority: "${currentPriority}"`, ); continue; // TODO Should we throw? Will this corrupt our data? } @@ -229,7 +229,7 @@ export default function reactProfilerProcessor( currentPriority !== name.substr(17) ) { console.error( - `Unexpected scheduler stop: "${name}" with current priority: "${currentPriority}"` + `Unexpected scheduler stop: "${name}" with current priority: "${currentPriority}"`, ); continue; // TODO Should we throw? Will this corrupt our data? } @@ -284,7 +284,7 @@ export default function reactProfilerProcessor( } else if (name.startsWith('--schedule-state-update-')) { const [componentName, componentStack] = name.substr(24).split('-'); const isCascading = !!currentMetadata.stack.find( - ({ type }) => type === 'commit' + ({type}) => type === 'commit', ); currentProfilerDataGroup.events.push({ type: 'schedule-state-update', @@ -307,29 +307,29 @@ export default function reactProfilerProcessor( } Object.entries(metadata).forEach(([priority, metadata]) => { - const { stack } = ((metadata: any): Metadata); + const {stack} = ((metadata: any): Metadata); if (stack.length > 0) { console.error( `Incomplete events or measures for priority ${priority}`, - stack + stack, ); } }); ['unscheduled', 'high', 'normal', 'low'].forEach(priority => { - const { events, measures } = reactProfilerData[priority]; + const {events, measures} = reactProfilerData[priority]; if (events.length > 0) { - const { timestamp } = (events[events.length - 1]: ReactEvent); + const {timestamp} = (events[events.length - 1]: ReactEvent); reactProfilerData.duration = Math.max( reactProfilerData.duration, - timestamp + timestamp, ); } if (measures.length > 0) { - const { duration, timestamp } = measures[measures.length - 1]; + const {duration, timestamp} = measures[measures.length - 1]; reactProfilerData.duration = Math.max( reactProfilerData.duration, - timestamp + duration + timestamp + duration, ); } }); diff --git a/src/util/preprocessFlamechart.js b/src/util/preprocessFlamechart.js index a2ee28348fb9e..6774f85c3567a 100644 --- a/src/util/preprocessFlamechart.js +++ b/src/util/preprocessFlamechart.js @@ -1,13 +1,13 @@ // @flow -import { importFromChromeTimeline } from '../speedscope/import/chrome'; -import { Flamechart } from '../speedscope/lib/flamechart'; +import {importFromChromeTimeline} from '../speedscope/import/chrome'; +import {Flamechart} from '../speedscope/lib/flamechart'; -import type { TimelineEvent } from './speedscope/import/chrome'; -import type { FlamechartData } from './types'; +import type {TimelineEvent} from './speedscope/import/chrome'; +import type {FlamechartData} from './types'; export default function preprocessFlamechart( - rawData: TimelineEvent[] + rawData: TimelineEvent[], ): FlamechartData { const parsedData = importFromChromeTimeline(rawData, 'react-devtools'); const profile = parsedData.profiles[0]; // TODO Choose the main CPU thread only diff --git a/src/util/useInteractiveEvents.js b/src/util/useInteractiveEvents.js index 2e163f0be735c..b2dc00d6b6146 100644 --- a/src/util/useInteractiveEvents.js +++ b/src/util/useInteractiveEvents.js @@ -1,11 +1,11 @@ // @flow -import { useEffect, useRef, useState } from 'react'; -import { durationToWidth, timestampToPosition } from './usePanAndZoom'; -import { EVENT_SIZE } from '../constants'; +import {useEffect, useRef, useState} from 'react'; +import {durationToWidth, timestampToPosition} from './usePanAndZoom'; +import {EVENT_SIZE} from '../constants'; function doesEventIntersectPosition(position, state, event) { - const { duration, timestamp } = event; + const {duration, timestamp} = event; // Although it would be intuitive to search by time, // that can result in a confusing user experience for events of 0ms duration- @@ -65,7 +65,7 @@ export default function useInteractiveEvents({ useEffect(() => { const onClick = () => { - const { hoveredEvent, selectedEvent } = lastResultRef.current; + const {hoveredEvent, selectedEvent} = lastResultRef.current; setSelectedEvent(hoveredEvent === selectedEvent ? null : hoveredEvent); }; const canvas = canvasRef.current; diff --git a/src/util/usePanAndZoom.js b/src/util/usePanAndZoom.js index 88d5e3a71df19..bf9ad4272e0dd 100644 --- a/src/util/usePanAndZoom.js +++ b/src/util/usePanAndZoom.js @@ -1,7 +1,7 @@ // @flow -import { useEffect, useReducer } from 'react'; -import { getCanvasMousePos } from '../canvas/canvasUtils'; +import {useEffect, useReducer} from 'react'; +import {getCanvasMousePos} from '../canvas/canvasUtils'; import { BAR_HORIZONTAL_SPACING, MAX_ZOOM_LEVEL, @@ -58,7 +58,7 @@ export function timestampToPosition(timestamp: number, state: PanAndZoomState) { export function durationToWidth(duration: number, state: PanAndZoomState) { return Math.max( duration * state.zoomLevel - BAR_HORIZONTAL_SPACING, - MIN_BAR_WIDTH + MIN_BAR_WIDTH, ); } @@ -116,11 +116,11 @@ function reducer( | MouseMoveAction | MouseUpAction | WheelAction - | ZoomToAction + | ZoomToAction, ): PanAndZoomState { switch (action.type) { case 'initialize': { - const { payload } = action; + const {payload} = action; return ({ ...state, canvasHeight: payload.canvasHeight, @@ -142,10 +142,10 @@ function reducer( }; } case 'mouse-move': { - const { payload } = action; - const { canvasMouseX, canvasMouseY } = getCanvasMousePos( + const {payload} = action; + const {canvasMouseX, canvasMouseY} = getCanvasMousePos( payload.canvas, - payload.event + payload.event, ); if (state.isDragging) { @@ -156,12 +156,12 @@ function reducer( offsetX: clamp( 0, getMaxOffsetX(state), - state.offsetX - payload.event.movementX + state.offsetX - payload.event.movementX, ), offsetY: clamp( 0, getMaxOffsetY(state), - state.offsetY + payload.event.movementY + state.offsetY + payload.event.movementY, ), }; } else { @@ -179,9 +179,9 @@ function reducer( }; } case 'wheel': { - const { payload } = action; - const { canvas, event } = payload; - const { deltaX, deltaY } = event; + const {payload} = action; + const {canvas, event} = payload; + const {deltaX, deltaY} = event; const { minZoomLevel, offsetX, @@ -204,14 +204,14 @@ function reducer( } else { if (event.shiftKey || event.ctrlKey || event.metaKey) { if (absDeltaY > ZOOM_WHEEL_DELTA_THRESHOLD) { - const { canvasMouseX } = getCanvasMousePos(canvas, event); + const {canvasMouseX} = getCanvasMousePos(canvas, event); const nextState = { ...state, zoomLevel: clamp( minZoomLevel, MAX_ZOOM_LEVEL, - zoomLevel * (1 + 0.005 * -deltaY) + zoomLevel * (1 + 0.005 * -deltaY), ), }; @@ -219,17 +219,17 @@ function reducer( // and adjust the offset so that point stays centered after zooming. const timestampAtCurrentZoomLevel = positionToTimestamp( canvasMouseX, - state + state, ); const positionAtNewZoom = timestampToPosition( timestampAtCurrentZoomLevel, - nextState + nextState, ); nextState.offsetX = clamp( 0, getMaxOffsetX(nextState), - offsetX + positionAtNewZoom - canvasMouseX + offsetX + positionAtNewZoom - canvasMouseX, ); if (nextState.zoomLevel !== zoomLevel) { @@ -248,9 +248,9 @@ function reducer( break; } case 'zoom-to': { - const { payload } = action; - const { startTime, stopTime } = payload; - const { canvasWidth, fixedColumnWidth } = state; + const {payload} = action; + const {startTime, stopTime} = payload; + const {canvasWidth, fixedColumnWidth} = state; const availableWidth = canvasWidth - fixedColumnWidth; const newZoomLevel = availableWidth / (stopTime - startTime); @@ -276,7 +276,7 @@ function clamp(min: number, max: number, value: number): number { } type Props = {| - canvasRef: {| current: HTMLCanvasElement | null |}, + canvasRef: {|current: HTMLCanvasElement | null|}, canvasHeight: number, canvasWidth: number, fixedColumnWidth: number, @@ -314,7 +314,7 @@ export default function usePanAndZoom({ const initialZoomLevel = clamp( MIN_ZOOM_LEVEL, MAX_ZOOM_LEVEL, - (width - fixedColumnWidth) / unscaledContentWidth + (width - fixedColumnWidth) / unscaledContentWidth, ); dispatch({ @@ -348,7 +348,7 @@ export default function usePanAndZoom({ } const onCanvasMouseDown: MouseEventHandler = event => { - dispatch({ type: 'mouse-down' }); + dispatch({type: 'mouse-down'}); }; const onCanvasMouseMove: MouseEventHandler = event => { @@ -362,7 +362,7 @@ export default function usePanAndZoom({ }; const onDocumentMouseUp: MouseEventHandler = event => { - dispatch({ type: 'mouse-up' }); + dispatch({type: 'mouse-up'}); }; const onCanvasWheel: WheelEventHandler = event => { diff --git a/src/util/useSmartTooltip.js b/src/util/useSmartTooltip.js index 2b877b87cf419..652721f96d2ad 100644 --- a/src/util/useSmartTooltip.js +++ b/src/util/useSmartTooltip.js @@ -1,6 +1,6 @@ // @flow -import { useLayoutEffect, useRef } from 'react'; +import {useLayoutEffect, useRef} from 'react'; const TOOLTIP_OFFSET = 4; diff --git a/yarn.lock b/yarn.lock index d963933b09203..8e86b73555abe 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7587,7 +7587,7 @@ prelude-ls@~1.1.2: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= -prettier@^1.19.1: +prettier@1.19.1: version "1.19.1" resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb" integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew== From bb64e8ca01802d5932e12de2b114689a766ca37d Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Fri, 26 Jun 2020 20:57:00 +0800 Subject: [PATCH 020/116] Add ESLint (#22) * Copy React's ESLint config * Add ESLint etc deps and lint script Copied from React, but we also upgrade all of them except eslint-config-fbjs. * Delete all irrelevant ESLint rules * Run yarn lint --fix * Fix lint * Replace single quotes in lint stript with double quotes * Add newline at end of .eslintignore --- .eslintignore | 5 + .eslintrc.js | 98 ++++++ package.json | 11 + src/App.js | 26 +- src/EventTooltip.js | 12 +- src/canvas/canvasUtils.js | 8 +- src/canvas/renderCanvas.js | 18 +- src/context/ContextMenu.js | 6 +- src/context/useContextMenu.js | 1 - src/types.js | 1 + src/util/preprocessData.js | 4 +- src/util/useInteractiveEvents.js | 9 +- src/util/usePanAndZoom.js | 13 +- yarn.lock | 568 ++++++++++++++++++++++++++++++- 14 files changed, 705 insertions(+), 75 deletions(-) create mode 100644 .eslintignore create mode 100644 .eslintrc.js diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000000000..d505ba5d8163c --- /dev/null +++ b/.eslintignore @@ -0,0 +1,5 @@ +node_modules/* +dist/* +static/* +src/speedscope/* +src/tracerbench/* diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000000000..f4887a8aa0c7d --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,98 @@ +'use strict'; + +const restrictedGlobals = require('confusing-browser-globals'); + +const OFF = 0; +const ERROR = 2; + +module.exports = { + extends: ['fbjs', 'prettier'], + + // Stop ESLint from looking for a configuration file in parent folders + root: true, + + plugins: ['jest', 'no-for-of-loops', 'react'], + + parser: 'babel-eslint', + parserOptions: { + ecmaVersion: 8, + sourceType: 'module', + ecmaFeatures: { + experimentalObjectRestSpread: true, + }, + }, + + // We're stricter than the default config, mostly. We'll override a few rules + // and then enable some React specific ones. + rules: { + 'accessor-pairs': OFF, + 'brace-style': [ERROR, '1tbs'], + 'consistent-return': OFF, + 'dot-location': [ERROR, 'property'], + // We use console['error']() as a signal to not transform it: + 'dot-notation': [ERROR, {allowPattern: '^(error|warn)$'}], + 'eol-last': ERROR, + eqeqeq: [ERROR, 'allow-null'], + indent: OFF, + 'jsx-quotes': [ERROR, 'prefer-double'], + 'keyword-spacing': [ERROR, {after: true, before: true}], + 'no-bitwise': OFF, + 'no-inner-declarations': [ERROR, 'functions'], + 'no-multi-spaces': ERROR, + 'no-restricted-globals': [ERROR].concat(restrictedGlobals), + 'no-restricted-syntax': [ERROR, 'WithStatement'], + 'no-shadow': ERROR, + 'no-unused-expressions': ERROR, + 'no-unused-vars': [ERROR, {args: 'none'}], + 'no-use-before-define': OFF, + 'no-useless-concat': OFF, + quotes: [ERROR, 'single', {avoidEscape: true, allowTemplateLiterals: true}], + 'space-before-blocks': ERROR, + 'space-before-function-paren': OFF, + 'valid-typeof': [ERROR, {requireStringLiterals: true}], + + 'no-var': ERROR, + 'prefer-const': ERROR, + strict: OFF, + + // Enforced by Prettier + // TODO: Prettier doesn't handle long strings or long comments. Not a big + // deal. But I turned it off because loading the plugin causes some obscure + // syntax error and it didn't seem worth investigating. + 'max-len': OFF, + + // React & JSX + // Our transforms set this automatically + 'react/jsx-boolean-value': [ERROR, 'always'], + 'react/jsx-no-undef': ERROR, + // We don't care to do this + 'react/jsx-sort-prop-types': OFF, + 'react/jsx-space-before-closing': ERROR, + 'react/jsx-uses-react': ERROR, + 'react/no-is-mounted': OFF, + // This isn't useful in our test code + 'react/react-in-jsx-scope': ERROR, + 'react/self-closing-comp': ERROR, + // We don't care to do this + 'react/jsx-wrap-multilines': [ + ERROR, + {declaration: false, assignment: false}, + ], + + // Prevent for...of loops because they require a Symbol polyfill. + // You can disable this rule for code that isn't shipped (e.g. build scripts and tests). + 'no-for-of-loops/no-for-of-loops': ERROR, + }, + + overrides: [ + { + files: ['**/__tests__/*.js'], + rules: { + // https://github.com/jest-community/eslint-plugin-jest + 'jest/no-focused-tests': ERROR, + 'jest/valid-expect': ERROR, + 'jest/valid-expect-in-promise': ERROR, + }, + }, + ], +}; diff --git a/package.json b/package.json index 61c4fa8c3a432..a075cf0894037 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "build": "parcel build index.html --no-cache", "prettier": "prettier --write \"**/*.{js,json,css}\"", "start": "parcel index.html --no-cache", + "lint": "eslint \"src/**/*.js\"", "test": "jest" }, "author": "Brian Vaughn ", @@ -25,8 +26,18 @@ "@babel/core": "^7.10.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.3.0", + "babel-eslint": "^10.1.0", "babel-jest": "^26.0.1", "babel-preset-react-app": "^9.1.2", + "confusing-browser-globals": "^1.0.9", + "eslint": "^7.3.1", + "eslint-config-fbjs": "^1.1.1", + "eslint-config-prettier": "^6.11.0", + "eslint-plugin-babel": "^5.3.0", + "eslint-plugin-flowtype": "^5.1.3", + "eslint-plugin-jest": "^23.17.1", + "eslint-plugin-no-for-of-loops": "^1.0.1", + "eslint-plugin-react": "^7.20.0", "flow-bin": "^0.127.0", "identity-obj-proxy": "^3.0.0", "jest": "^26.0.1", diff --git a/src/App.js b/src/App.js index 9934e66ff969e..a01446a2d5d21 100644 --- a/src/App.js +++ b/src/App.js @@ -12,7 +12,6 @@ import React, { useState, } from 'react'; import {unstable_batchedUpdates} from 'react-dom'; -import memoize from 'memoize-one'; import usePanAndZoom from './util/usePanAndZoom'; import {getHoveredEvent, getPriorityHeight} from './canvas/canvasUtils'; @@ -42,10 +41,8 @@ const CONTEXT_MENU_ID = 'canvas'; import type { FlamechartData, - ReactEvent, ReactHoverContextInfo, ReactMeasure, - ReactPriority, ReactProfilerData, } from './types'; @@ -63,20 +60,19 @@ function App() { useEffect(() => { fetch(JSON_PATH) - .then(data => data.json()) - .then((data: TimelineEvent[]) => { + .then(res => res.json()) + .then((events: TimelineEvent[]) => { // Filter null entries and sort by timestamp. // I would not expect to have to do either of this, // but some of the data being passed in requires it. - data = data.filter(Boolean).sort((a, b) => (a.ts > b.ts ? 1 : -1)); + events = events.filter(Boolean).sort((a, b) => (a.ts > b.ts ? 1 : -1)); - if (data.length > 0) { + if (events.length > 0) { unstable_batchedUpdates(() => { - const processedData = preprocessData(data); + const processedData = preprocessData(events); setData(processedData); - const flamechart = preprocessFlamechart(data); - setFlamechart(flamechart); + setFlamechart(preprocessFlamechart(events)); let height = 0; @@ -211,11 +207,11 @@ function AutoSizedCanvas({ width={width} /> - {({data, hoveredEvent}: ContextMenuContextData) => { - if (hoveredEvent == null) { + {(contextData: ContextMenuContextData) => { + if (contextData.hoveredEvent == null) { return null; } - const {event, flamechartNode, measure} = hoveredEvent; + const {event, flamechartNode, measure} = contextData.hoveredEvent; return ( {event !== null && ( @@ -234,14 +230,14 @@ function AutoSizedCanvas({ )} {measure !== null && ( zoomToBatch(data, measure, state)} + onClick={() => zoomToBatch(contextData.data, measure, state)} title="Zoom to batch"> Zoom to batch )} {measure !== null && ( copySummary(data, measure)} + onClick={() => copySummary(contextData.data, measure)} title="Copy summary"> Copy summary diff --git a/src/EventTooltip.js b/src/EventTooltip.js index 1210e8177729d..a9b5037dfd566 100644 --- a/src/EventTooltip.js +++ b/src/EventTooltip.js @@ -11,14 +11,12 @@ import type { } from './types'; import prettyMilliseconds from 'pretty-ms'; -import React, {Fragment, useLayoutEffect, useRef} from 'react'; +import React, {Fragment, useRef} from 'react'; import {COLORS} from './canvas/constants'; import {getBatchRange} from './util/getBatchRange'; import useSmartTooltip from './util/useSmartTooltip'; import styles from './EventTooltip.css'; -const TOOLTIP_OFFSET = 4; - type Props = {| data: ReactProfilerData | null, hoveredEvent: ReactHoverContextInfo | null, @@ -105,13 +103,7 @@ export default function EventTooltip({data, hoveredEvent, state}: Props) { return null; } -declare function formatComponentStack(componentStack: null): null; -declare function formatComponentStack(componentStack: string): string; -function formatComponentStack(componentStack: string | null): string | null { - if (componentStack == null) { - return null; - } - +function formatComponentStack(componentStack: string): string { const lines = componentStack.split('\n').map(line => line.trim()); lines.shift(); diff --git a/src/canvas/canvasUtils.js b/src/canvas/canvasUtils.js index 7faf511b8e470..5f92bd0036d29 100644 --- a/src/canvas/canvasUtils.js +++ b/src/canvas/canvasUtils.js @@ -22,7 +22,7 @@ import { REACT_PRIORITY_BORDER_SIZE, FLAMECHART_FRAME_HEIGHT, } from './constants'; -import usePanAndZoom, { +import { durationToWidth, positionToTimestamp, timestampToPosition, @@ -126,7 +126,7 @@ export function getHoveredEvent( if (canvasMouseY + offsetY < schedulerCanvasHeight) { if (data != null) { - let adjustedCanvasMouseY = canvasMouseY - HEADER_HEIGHT_FIXED + offsetY; + const adjustedCanvasMouseY = canvasMouseY - HEADER_HEIGHT_FIXED + offsetY; let priorityMinY = HEADER_HEIGHT_FIXED; let priorityIndex = null; let priority: ReactPriority = 'unscheduled'; @@ -154,8 +154,8 @@ export function getHoveredEvent( const measureMinY = eventMaxY; const measureMaxY = measureMinY + REACT_WORK_SIZE + REACT_GUTTER_SIZE; - let events = null, - measures = null; + let events = null; + let measures = null; if (canvasMouseY >= eventMinY && canvasMouseY <= eventMaxY) { events = data[priority].events; } else if (canvasMouseY >= measureMinY && canvasMouseY <= measureMaxY) { diff --git a/src/canvas/renderCanvas.js b/src/canvas/renderCanvas.js index 06de2c3a35c91..ea116126b21d9 100644 --- a/src/canvas/renderCanvas.js +++ b/src/canvas/renderCanvas.js @@ -7,10 +7,9 @@ import type { } from '../types'; import type {PanAndZoomState} from '../util/usePanAndZoom'; -import React from 'react'; import memoize from 'memoize-one'; -import usePanAndZoom, { +import { durationToWidth, positionToTimestamp, timestampToPosition, @@ -35,7 +34,6 @@ import { REACT_GUTTER_SIZE, REACT_EVENT_SIZE, REACT_WORK_SIZE, - REACT_EVENT_BORDER_SIZE, REACT_PRIORITY_BORDER_SIZE, FLAMECHART_FONT_SIZE, FLAMECHART_FRAME_HEIGHT, @@ -154,8 +152,6 @@ export const renderReact = ({ y = baseY + REACT_WORK_SIZE * depth + REACT_GUTTER_SIZE * depth - offsetY; - const lineWidth = Math.floor(REACT_EVENT_BORDER_SIZE); - // $FlowFixMe We know these won't be null context.fillStyle = showHoverHighlight ? hoveredFillStyle @@ -329,15 +325,15 @@ export const renderCanvas = memoize( for (let i = 0; i < flamechart.layers.length; i++) { const nodes = flamechart.layers[i]; - const y = Math.floor( + const layerY = Math.floor( HEADER_HEIGHT_FIXED + schedulerCanvasHeight + i * FLAMECHART_FRAME_HEIGHT - offsetY, ); if ( - y + FLAMECHART_FRAME_HEIGHT < HEADER_HEIGHT_FIXED || - canvasHeight < y + layerY + FLAMECHART_FRAME_HEIGHT < HEADER_HEIGHT_FIXED || + canvasHeight < layerY ) { continue; // Not in view } @@ -346,7 +342,7 @@ export const renderCanvas = memoize( const {end, node, start} = nodes[j]; const {name} = node.frame; - let showHoverHighlight = + const showHoverHighlight = hoveredEvent && hoveredEvent.flamechartNode === nodes[j]; const width = durationToWidth((end - start) / 1000, state); @@ -365,7 +361,7 @@ export const renderCanvas = memoize( context.fillRect( x, - y, + layerY, Math.floor(width - REACT_PRIORITY_BORDER_SIZE), Math.floor(FLAMECHART_FRAME_HEIGHT - REACT_PRIORITY_BORDER_SIZE), ); @@ -381,7 +377,7 @@ export const renderCanvas = memoize( context.fillText( trimmedName, x + FLAMECHART_TEXT_PADDING - (x < 0 ? x : 0), - y + FLAMECHART_FRAME_HEIGHT / 2, + layerY + FLAMECHART_FRAME_HEIGHT / 2, ); } } diff --git a/src/context/ContextMenu.js b/src/context/ContextMenu.js index bc678c141af25..e20ed6af91d89 100644 --- a/src/context/ContextMenu.js +++ b/src/context/ContextMenu.js @@ -75,11 +75,11 @@ export default function ContextMenu({children, id}: Props) { }, [bodyAccessorRef, containerRef]); useEffect(() => { - const showMenu = ({data, pageX, pageY}) => { + const showMenuFn = ({data, pageX, pageY}) => { setState({data, isVisible: true, pageX, pageY}); }; - const hideMenu = () => setState(HIDDEN_STATE); - return registerMenu(id, showMenu, hideMenu); + const hideMenuFn = () => setState(HIDDEN_STATE); + return registerMenu(id, showMenuFn, hideMenuFn); }, [id]); useLayoutEffect(() => { diff --git a/src/context/useContextMenu.js b/src/context/useContextMenu.js index 5fcb094217446..214fa3e45b1a3 100644 --- a/src/context/useContextMenu.js +++ b/src/context/useContextMenu.js @@ -3,7 +3,6 @@ import {useContext, useEffect, useRef} from 'react'; import {RegistryContext} from './Contexts'; -import type {ElementRef} from 'react'; import type {OnChangeFn} from './Contexts'; import type {Return} from '../types'; diff --git a/src/types.js b/src/types.js index 853210528b014..e191d049bef33 100644 --- a/src/types.js +++ b/src/types.js @@ -5,6 +5,7 @@ import type {Flamechart, FlamechartFrame} from './speedscope/lib/flamechart'; // Type utilities // Source: https://github.com/facebook/flow/issues/4002#issuecomment-323612798 +// eslint-disable-next-line no-unused-vars type Return_) => R> = R; /** Get return type of a function. */ export type Return = Return_<*, T>; diff --git a/src/util/preprocessData.js b/src/util/preprocessData.js index 1cb58fcc3c6db..fda39690decb5 100644 --- a/src/util/preprocessData.js +++ b/src/util/preprocessData.js @@ -306,8 +306,8 @@ export default function reactProfilerProcessor( } } - Object.entries(metadata).forEach(([priority, metadata]) => { - const {stack} = ((metadata: any): Metadata); + Object.entries(metadata).forEach(([priority, metadataForPriority]) => { + const {stack} = ((metadataForPriority: any): Metadata); if (stack.length > 0) { console.error( `Incomplete events or measures for priority ${priority}`, diff --git a/src/util/useInteractiveEvents.js b/src/util/useInteractiveEvents.js index b2dc00d6b6146..e4f2c5e148bfa 100644 --- a/src/util/useInteractiveEvents.js +++ b/src/util/useInteractiveEvents.js @@ -42,7 +42,6 @@ export default function useInteractiveEvents({ canvasMouseY, fixedColumnWidth, fixedHeaderHeight, - zoomLevel, } = state; let hoveredEvent = null; @@ -65,8 +64,12 @@ export default function useInteractiveEvents({ useEffect(() => { const onClick = () => { - const {hoveredEvent, selectedEvent} = lastResultRef.current; - setSelectedEvent(hoveredEvent === selectedEvent ? null : hoveredEvent); + setSelectedEvent( + lastResultRef.current.hoveredEvent === + lastResultRef.current.selectedEvent + ? null + : lastResultRef.current.hoveredEvent, + ); }; const canvas = canvasRef.current; canvas.addEventListener('click', onClick); diff --git a/src/util/usePanAndZoom.js b/src/util/usePanAndZoom.js index bf9ad4272e0dd..9df8dd898cd62 100644 --- a/src/util/usePanAndZoom.js +++ b/src/util/usePanAndZoom.js @@ -182,14 +182,7 @@ function reducer( const {payload} = action; const {canvas, event} = payload; const {deltaX, deltaY} = event; - const { - minZoomLevel, - offsetX, - offsetY, - unscaledContentHeight, - unscaledContentWidth, - zoomLevel, - } = state; + const {minZoomLevel, offsetX, offsetY, zoomLevel} = state; const absDeltaX = Math.abs(deltaX); const absDeltaY = Math.abs(deltaY); @@ -270,7 +263,9 @@ function reducer( function clamp(min: number, max: number, value: number): number { if (Number.isNaN(min) || Number.isNaN(max) || Number.isNaN(value)) { - debugger; + throw new Error( + `Clamp was called with NaN. Args: min: ${min}, max: ${max}, value: ${value}.`, + ); } return Math.max(min, Math.min(max, value)); } diff --git a/yarn.lock b/yarn.lock index 8e86b73555abe..6b2ce5ffdb702 100644 --- a/yarn.lock +++ b/yarn.lock @@ -534,7 +534,7 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.7.tgz#1b886595419cf92d811316d5b715a53ff38b4937" integrity sha512-WtTZMZAZLbeymhkd/sEaPD8IQyGAhmuTuvTzLiCFM7iXiVdY0gc0IaI+cW0fh1BnSMbJSzXX6/fHllgHKwHhXw== -"@babel/parser@^7.1.0", "@babel/parser@^7.10.3", "@babel/parser@^7.9.0": +"@babel/parser@^7.1.0", "@babel/parser@^7.10.3", "@babel/parser@^7.7.0", "@babel/parser@^7.9.0": version "7.10.3" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.10.3.tgz#7e71d892b0d6e7d04a1af4c3c79d72c1f10f5315" integrity sha512-oJtNJCMFdIMwXGmx+KxuaD7i3b8uS7TTFYW/FNG2BT8m+fmGHoiPYoH0Pe3gya07WuFmM5FCDIr1x0irkD/hyA== @@ -1629,7 +1629,7 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-transform-typescript" "^7.9.0" -"@babel/runtime-corejs3@^7.10.2": +"@babel/runtime-corejs3@^7.10.2", "@babel/runtime-corejs3@^7.8.3": version "7.10.3" resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.10.3.tgz#931ed6941d3954924a7aa967ee440e60c507b91a" integrity sha512-HA7RPj5xvJxQl429r5Cxr2trJwOfPjKiqhCXcdQPSqO2G0RHPZpXu4fkYmBaTKCp2c/jRaMK9GB/lN+7zvvFPw== @@ -1684,7 +1684,7 @@ globals "^11.1.0" lodash "^4.17.13" -"@babel/traverse@^7.1.0", "@babel/traverse@^7.10.1", "@babel/traverse@^7.10.3", "@babel/traverse@^7.9.0": +"@babel/traverse@^7.1.0", "@babel/traverse@^7.10.1", "@babel/traverse@^7.10.3", "@babel/traverse@^7.7.0", "@babel/traverse@^7.9.0": version "7.10.3" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.10.3.tgz#0b01731794aa7b77b214bcd96661f18281155d7e" integrity sha512-qO6623eBFhuPm0TmmrUFMT1FulCmsSeJuVGhiLodk2raUDFhhTECLd9E9jC4LBIWziqt4wgF6KuXE4d+Jz9yug== @@ -1708,7 +1708,7 @@ lodash "^4.17.13" to-fast-properties "^2.0.0" -"@babel/types@^7.10.1", "@babel/types@^7.10.3", "@babel/types@^7.3.0", "@babel/types@^7.4.4", "@babel/types@^7.9.0": +"@babel/types@^7.10.1", "@babel/types@^7.10.3", "@babel/types@^7.3.0", "@babel/types@^7.4.4", "@babel/types@^7.7.0", "@babel/types@^7.9.0": version "7.10.3" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.10.3.tgz#6535e3b79fea86a6b09e012ea8528f935099de8e" integrity sha512-nZxaJhBXBQ8HVoIcGsf9qWep3Oh3jCENK54V4mRF7qaJabVsAYdbTtmSD8WmAp1R6ytPiu5apMwSXyxB1WlaBA== @@ -2700,6 +2700,11 @@ jest-diff "^25.2.1" pretty-format "^25.2.1" +"@types/json-schema@^7.0.3": + version "7.0.5" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.5.tgz#dcce4430e64b443ba8945f0290fb564ad5bac6dd" + integrity sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ== + "@types/node@*": version "14.0.13" resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.13.tgz#ee1128e881b874c371374c1f72201893616417c9" @@ -2749,6 +2754,29 @@ dependencies: "@types/yargs-parser" "*" +"@typescript-eslint/experimental-utils@^2.5.0": + version "2.34.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.34.0.tgz#d3524b644cdb40eebceca67f8cf3e4cc9c8f980f" + integrity sha512-eS6FTkq+wuMJ+sgtuNTtcqavWXqsflWcfBnlYhg/nS4aZ1leewkXGbvBhaapn1q6qf4M71bsR1tez5JTRMuqwA== + dependencies: + "@types/json-schema" "^7.0.3" + "@typescript-eslint/typescript-estree" "2.34.0" + eslint-scope "^5.0.0" + eslint-utils "^2.0.0" + +"@typescript-eslint/typescript-estree@2.34.0": + version "2.34.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.34.0.tgz#14aeb6353b39ef0732cc7f1b8285294937cf37d5" + integrity sha512-OMAr+nJWKdlVM9LOqCqh3pQQPwxHAN7Du8DR6dmwCrAmxtiXQnhHJ6tBNtf+cggqfo51SG/FCwnKhXCIM7hnVg== + dependencies: + debug "^4.1.1" + eslint-visitor-keys "^1.1.0" + glob "^7.1.6" + is-glob "^4.0.1" + lodash "^4.17.15" + semver "^7.3.2" + tsutils "^3.17.1" + abab@^2.0.0, abab@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.3.tgz#623e2075e02eb2d3f2475e49f99c91846467907a" @@ -2780,6 +2808,11 @@ acorn-globals@^6.0.0: acorn "^7.1.1" acorn-walk "^7.1.1" +acorn-jsx@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.2.0.tgz#4c66069173d6fdd68ed85239fc256226182b2ebe" + integrity sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ== + acorn-walk@^6.0.1: version "6.2.0" resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.2.0.tgz#123cb8f3b84c2171f1f7fb252615b1c78a6b1a8c" @@ -2800,11 +2833,21 @@ acorn@^6.0.1, acorn@^6.0.4: resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.0.tgz#b659d2ffbafa24baf5db1cdbb2c94a983ecd2784" integrity sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw== -acorn@^7.1.1: +acorn@^7.1.1, acorn@^7.2.0: version "7.3.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.3.1.tgz#85010754db53c3fbaf3b9ea3e083aa5c5d147ffd" integrity sha512-tLc0wSnatxAQHVHUapaHdz72pi9KUyHjq5KyHjGg9Y8Ifdc79pTh2XvI6I1/chZbnM7QtNKzh66ooDogPZSleA== +ajv@^6.10.0, ajv@^6.10.2: + version "6.12.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.2.tgz#c629c5eced17baf314437918d2da88c99d5958cd" + integrity sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + ajv@^6.5.5: version "6.10.2" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.2.tgz#d3cea04d6b017b2894ad69040fec8b623eb4bd52" @@ -2820,6 +2863,11 @@ alphanum-sort@^1.0.0: resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" integrity sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM= +ansi-colors@^3.2.1: + version "3.2.4" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf" + integrity sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA== + ansi-escapes@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" @@ -2946,6 +2994,15 @@ array-equal@^1.0.0: resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93" integrity sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM= +array-includes@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.1.tgz#cdd67e6852bdf9c1215460786732255ed2459348" + integrity sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0" + is-string "^1.0.5" + array-unique@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" @@ -3030,6 +3087,18 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.0.tgz#24390e6ad61386b0a747265754d2a17219de862c" integrity sha512-Uvq6hVe90D0B2WEnUqtdgY1bATGz3mw33nH9Y+dmA+w5DHvUmBgkr5rM/KCHpCsiFNRUfokW/szpPPgMK2hm4A== +babel-eslint@^10.1.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.1.0.tgz#6968e568a910b78fb3779cdd8b6ac2f479943232" + integrity sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg== + dependencies: + "@babel/code-frame" "^7.0.0" + "@babel/parser" "^7.7.0" + "@babel/traverse" "^7.7.0" + "@babel/types" "^7.7.0" + eslint-visitor-keys "^1.0.0" + resolve "^1.12.0" + babel-jest@^26.0.1: version "26.0.1" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-26.0.1.tgz#450139ce4b6c17174b136425bda91885c397bc46" @@ -3738,6 +3807,11 @@ config-chain@^1.1.12: ini "^1.3.4" proto-list "~1.2.1" +confusing-browser-globals@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.9.tgz#72bc13b483c0276801681871d4898516f8f54fdd" + integrity sha512-KbS1Y0jMtyPgIxjO7ZzMAuUpAKMt1SzCL9fsrKsX6b0zJPTaT0SiSPmewwVZg9UAO83HVIlEhZF84LIjZ0lmAw== + connect@^3.7.0: version "3.7.0" resolved "https://registry.yarnpkg.com/connect/-/connect-3.7.0.tgz#5d49348910caa5e07a01800b030d0c35f20484f8" @@ -3874,7 +3948,7 @@ cross-spawn@^6.0.0, cross-spawn@^6.0.4: shebang-command "^1.2.0" which "^1.2.9" -cross-spawn@^7.0.0: +cross-spawn@^7.0.0, cross-spawn@^7.0.2: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -4148,7 +4222,7 @@ debug@^3.0.0: dependencies: ms "^2.1.1" -debug@^4.1.0, debug@^4.1.1: +debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== @@ -4182,7 +4256,7 @@ deep-extend@^0.6.0: resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== -deep-is@~0.1.3: +deep-is@^0.1.3, deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= @@ -4268,6 +4342,20 @@ diffie-hellman@^5.0.0: miller-rabin "^4.0.0" randombytes "^2.0.0" +doctrine@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== + dependencies: + esutils "^2.0.2" + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + dom-accessibility-api@^0.4.5: version "0.4.5" resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.4.5.tgz#d9c1cefa89f509d8cf132ab5d250004d755e76e3" @@ -4436,6 +4524,13 @@ end-of-stream@^1.1.0, end-of-stream@^1.4.1: dependencies: once "^1.4.0" +enquirer@^2.3.5: + version "2.3.5" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.5.tgz#3ab2b838df0a9d8ab9e7dff235b0e8712ef92381" + integrity sha512-BNT1C08P9XD0vNg3J475yIUG+mVdp9T6towYFHUv897X0KoHBjB1shyrNmhmtHWKP17iSWgo7Gqh7BBuzLZMSA== + dependencies: + ansi-colors "^3.2.1" + entities@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" @@ -4453,6 +4548,23 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" +es-abstract@^1.17.0, es-abstract@^1.17.5: + version "1.17.6" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.6.tgz#9142071707857b2cacc7b89ecb670316c3e2d52a" + integrity sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw== + dependencies: + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + is-callable "^1.2.0" + is-regex "^1.1.0" + object-inspect "^1.7.0" + object-keys "^1.1.1" + object.assign "^4.1.0" + string.prototype.trimend "^1.0.1" + string.prototype.trimstart "^1.0.1" + es-abstract@^1.17.0-next.1: version "1.17.0" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.0.tgz#f42a517d0036a5591dbb2c463591dc8bb50309b1" @@ -4530,6 +4642,138 @@ escodegen@~1.9.0: optionalDependencies: source-map "~0.6.1" +eslint-config-fbjs@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/eslint-config-fbjs/-/eslint-config-fbjs-1.1.1.tgz#dd29f8d912e8a755257e9eeef00bae1cce57f73a" + integrity sha1-3Sn42RLop1Ulfp7u8AuuHM5X9zo= + +eslint-config-prettier@^6.11.0: + version "6.11.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.11.0.tgz#f6d2238c1290d01c859a8b5c1f7d352a0b0da8b1" + integrity sha512-oB8cpLWSAjOVFEJhhyMZh6NOEOtBVziaqdDQ86+qhDHFbZXoRTM7pNSvFRfW/W/L/LrQ38C99J5CGuRBBzBsdA== + dependencies: + get-stdin "^6.0.0" + +eslint-plugin-babel@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-babel/-/eslint-plugin-babel-5.3.0.tgz#2e7f251ccc249326da760c1a4c948a91c32d0023" + integrity sha512-HPuNzSPE75O+SnxHIafbW5QB45r2w78fxqwK3HmjqIUoPfPzVrq6rD+CINU3yzoDSzEhUkX07VUphbF73Lth/w== + dependencies: + eslint-rule-composer "^0.3.0" + +eslint-plugin-flowtype@^5.1.3: + version "5.1.3" + resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-5.1.3.tgz#0c63694463b0e8b296975649d637dd39fdf9e877" + integrity sha512-UU+BbIxBflqJ171yxbd/HcOktCmOdhXbchIVIq/yBvKpLZXvfzNDOyJGcnuQYLaH840hdoIdU/bqxhoW6I0rIQ== + dependencies: + lodash "^4.17.15" + string-natural-compare "^3.0.1" + +eslint-plugin-jest@^23.17.1: + version "23.17.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-23.17.1.tgz#c0f39ba78e0f33b7ee1ce4ec92b773e39026ea3f" + integrity sha512-/o36fw67qNbJGWbSBIBMfseMsNP/d88WUHAGHCi1xFwsNB3XXZGdvxbOw49j3iQz6MCW/yw8OeOsuQhi6mM5ZA== + dependencies: + "@typescript-eslint/experimental-utils" "^2.5.0" + +eslint-plugin-no-for-of-loops@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-no-for-of-loops/-/eslint-plugin-no-for-of-loops-1.0.1.tgz#2ee3732d50c642b8d1bfacedbfe3b28f86222369" + integrity sha512-uCotzBHt2W+HbLw2srRmqDJHOPbJGzeVLstKh8YyxS3ppduq2P50qdpJfHKoD+UGbnqA/zhy8NRgPH6p0y8bnA== + +eslint-plugin-react@^7.20.0: + version "7.20.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.20.0.tgz#f98712f0a5e57dfd3e5542ef0604b8739cd47be3" + integrity sha512-rqe1abd0vxMjmbPngo4NaYxTcR3Y4Hrmc/jg4T+sYz63yqlmJRknpEQfmWY+eDWPuMmix6iUIK+mv0zExjeLgA== + dependencies: + array-includes "^3.1.1" + doctrine "^2.1.0" + has "^1.0.3" + jsx-ast-utils "^2.2.3" + object.entries "^1.1.1" + object.fromentries "^2.0.2" + object.values "^1.1.1" + prop-types "^15.7.2" + resolve "^1.15.1" + string.prototype.matchall "^4.0.2" + xregexp "^4.3.0" + +eslint-rule-composer@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz#79320c927b0c5c0d3d3d2b76c8b4a488f25bbaf9" + integrity sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg== + +eslint-scope@^5.0.0, eslint-scope@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.0.tgz#d0f971dfe59c69e0cada684b23d49dbf82600ce5" + integrity sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w== + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + +eslint-utils@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" + integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== + dependencies: + eslint-visitor-keys "^1.1.0" + +eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.2.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" + integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== + +eslint@^7.3.1: + version "7.3.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.3.1.tgz#76392bd7e44468d046149ba128d1566c59acbe19" + integrity sha512-cQC/xj9bhWUcyi/RuMbRtC3I0eW8MH0jhRELSvpKYkWep3C6YZ2OkvcvJVUeO6gcunABmzptbXBuDoXsjHmfTA== + dependencies: + "@babel/code-frame" "^7.0.0" + ajv "^6.10.0" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.0.1" + doctrine "^3.0.0" + enquirer "^2.3.5" + eslint-scope "^5.1.0" + eslint-utils "^2.0.0" + eslint-visitor-keys "^1.2.0" + espree "^7.1.0" + esquery "^1.2.0" + esutils "^2.0.2" + file-entry-cache "^5.0.1" + functional-red-black-tree "^1.0.1" + glob-parent "^5.0.0" + globals "^12.1.0" + ignore "^4.0.6" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + js-yaml "^3.13.1" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash "^4.17.14" + minimatch "^3.0.4" + natural-compare "^1.4.0" + optionator "^0.9.1" + progress "^2.0.0" + regexpp "^3.1.0" + semver "^7.2.1" + strip-ansi "^6.0.0" + strip-json-comments "^3.1.0" + table "^5.2.3" + text-table "^0.2.0" + v8-compile-cache "^2.0.3" + +espree@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-7.1.0.tgz#a9c7f18a752056735bf1ba14cb1b70adc3a5ce1c" + integrity sha512-dcorZSyfmm4WTuTnE5Y7MEN1DyoPYy1ZR783QW1FJoenn7RailyWFsq/UL6ZAAA7uXurN9FIpYyUs3OfiIW+Qw== + dependencies: + acorn "^7.2.0" + acorn-jsx "^5.2.0" + eslint-visitor-keys "^1.2.0" + esprima@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" @@ -4540,11 +4784,30 @@ esprima@^4.0.0, esprima@^4.0.1: resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -estraverse@^4.2.0: +esquery@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.3.1.tgz#b78b5828aa8e214e29fb74c4d5b752e1c033da57" + integrity sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.1.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" + integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ== + dependencies: + estraverse "^4.1.0" + +estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: version "4.3.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== +estraverse@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.1.0.tgz#374309d39fd935ae500e7b92e8a6b4c720e59642" + integrity sha512-FyohXK+R0vE+y1nHLoBM7ZTyqRpqAlhdZHCWIWEviFLiGB8b04H6bQs8G+XTthacvT8VuwvteiP7RJSxMs8UEw== + esutils@^2.0.0, esutils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" @@ -4695,6 +4958,11 @@ fast-deep-equal@^2.0.1: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= +fast-deep-equal@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + fast-glob@^3.0.4: version "3.1.1" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.1.1.tgz#87ee30e9e9f3eb40d6f254a7997655da753d7c82" @@ -4711,7 +4979,7 @@ fast-json-stable-stringify@^2.0.0: resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== -fast-levenshtein@~2.0.6: +fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= @@ -4742,6 +5010,13 @@ fb-watchman@^2.0.0: dependencies: bser "2.1.1" +file-entry-cache@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" + integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== + dependencies: + flat-cache "^2.0.1" + file-uri-to-path@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" @@ -4804,6 +5079,20 @@ find-up@^4.0.0, find-up@^4.1.0: locate-path "^5.0.0" path-exists "^4.0.0" +flat-cache@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" + integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== + dependencies: + flatted "^2.0.0" + rimraf "2.6.3" + write "1.0.3" + +flatted@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" + integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== + flow-bin@^0.127.0: version "0.127.0" resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.127.0.tgz#0614cff4c1b783beef1feeb7108d536e09d77632" @@ -4872,6 +5161,11 @@ function-bind@^1.1.1: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +functional-red-black-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= + gauge@~2.7.3: version "2.7.4" resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" @@ -4913,6 +5207,11 @@ get-port@^4.2.0: resolved "https://registry.yarnpkg.com/get-port/-/get-port-4.2.0.tgz#e37368b1e863b7629c43c5a323625f95cf24b119" integrity sha512-/b3jarXkH8KJoOMQc3uVGHASwGLPq3gSFJ7tgJm2diza+bydJPTGOibin2steecKeOylE8oY2JERlVWkAJO6yw== +get-stdin@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" + integrity sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g== + get-stream@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" @@ -4944,6 +5243,13 @@ github-from-package@0.0.0: resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" integrity sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4= +glob-parent@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" + integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== + dependencies: + is-glob "^4.0.1" + glob-parent@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.0.tgz#5f4c1d1e748d30cd73ad2944b3577a81b081e8c2" @@ -4951,7 +5257,7 @@ glob-parent@^5.1.0: dependencies: is-glob "^4.0.1" -glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4: +glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== @@ -4968,6 +5274,13 @@ globals@^11.1.0: resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== +globals@^12.1.0: + version "12.4.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-12.4.0.tgz#a18813576a41b00a24a97e7f815918c2e19925f8" + integrity sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg== + dependencies: + type-fest "^0.8.1" + graceful-fs@^4.2.4: version "4.2.4" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" @@ -5241,6 +5554,11 @@ ieee754@^1.1.4: resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg== +ignore@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" + integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== + import-fresh@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" @@ -5249,7 +5567,7 @@ import-fresh@^2.0.0: caller-path "^2.0.0" resolve-from "^3.0.0" -import-fresh@^3.1.0: +import-fresh@^3.0.0, import-fresh@^3.1.0: version "3.2.1" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.2.1.tgz#633ff618506e793af5ac91bf48b72677e15cbe66" integrity sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ== @@ -5340,6 +5658,15 @@ ink@^2.1.1: wrap-ansi "^6.2.0" yoga-layout-prebuilt "^1.9.3" +internal-slot@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.2.tgz#9c2e9fb3cd8e5e4256c6f45fe310067fcfa378a3" + integrity sha512-2cQNfwhAfJIkU4KZPkDI+Gj5yNNnbqi40W9Gge6dfnk4TocEVm00B3bdiL+JINrbGJil2TeHvM4rETGzk/f/0g== + dependencies: + es-abstract "^1.17.0-next.1" + has "^1.0.3" + side-channel "^1.0.2" + invariant@^2.2.2, invariant@^2.2.4: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" @@ -5396,6 +5723,11 @@ is-callable@^1.1.4, is-callable@^1.1.5: resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab" integrity sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q== +is-callable@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.0.tgz#83336560b54a38e35e3a2df7afd0454d691468bb" + integrity sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw== + is-ci@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" @@ -5551,6 +5883,13 @@ is-regex@^1.0.5: dependencies: has "^1.0.3" +is-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.0.tgz#ece38e389e490df0dc21caea2bd596f987f767ff" + integrity sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw== + dependencies: + has-symbols "^1.0.1" + is-resolvable@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" @@ -5566,6 +5905,11 @@ is-stream@^2.0.0: resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== +is-string@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.5.tgz#40493ed198ef3ff477b8c7f92f644ec82a5cd3a6" + integrity sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ== + is-svg@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-3.0.0.tgz#9321dbd29c212e5ca99c4fa9794c714bcafa2f75" @@ -6193,6 +6537,11 @@ json-source-map@^0.6.1: resolved "https://registry.yarnpkg.com/json-source-map/-/json-source-map-0.6.1.tgz#e0b1f6f4ce13a9ad57e2ae165a24d06e62c79a0f" integrity sha512-1QoztHPsMQqhDq0hlXY5ZqcEdUzxQEIxgFkKl4WUp2pgShObl+9ovi4kRh2TfvAfxAoHOJ9vIMEqk3k4iex7tg== +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= + json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" @@ -6229,6 +6578,14 @@ jsprim@^1.2.2: json-schema "0.2.3" verror "1.10.0" +jsx-ast-utils@^2.2.3: + version "2.4.1" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.4.1.tgz#1114a4c1209481db06c690c2b4f488cc665f657e" + integrity sha512-z1xSldJ6imESSzOjd3NNkieVJKRlKYSOtMG8SFyCj2FIrvSaSuli/WjpBkEzCBoR9bYYYFgqJw61Xhu7Lcgk+w== + dependencies: + array-includes "^3.1.1" + object.assign "^4.1.0" + kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" @@ -6270,6 +6627,14 @@ levenary@^1.1.1: dependencies: leven "^3.1.0" +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + levn@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" @@ -6350,7 +6715,7 @@ lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.15, lodash@^4.17.4: +lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== @@ -6844,6 +7209,25 @@ object.assign@^4.1.0: has-symbols "^1.0.0" object-keys "^1.0.11" +object.entries@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.2.tgz#bc73f00acb6b6bb16c203434b10f9a7e797d3add" + integrity sha512-BQdB9qKmb/HyNdMNWVr7O3+z5MUIx3aiegEIJqjMBbBf0YT9RRxTJSim4mzFqtyr7PDAHigq0N9dO0m0tRakQA== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.5" + has "^1.0.3" + +object.fromentries@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.2.tgz#4a09c9b9bb3843dd0f89acdb517a794d4f355ac9" + integrity sha512-r3ZiBH7MQppDJVLx6fhD618GKNG40CZYH9wgwdhKxBDDbQgjeWGGd4AtkZad84d291YxvWe7bJGuE65Anh0dxQ== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" + function-bind "^1.1.1" + has "^1.0.3" + object.getownpropertydescriptors@^2.0.3: version "2.1.0" resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz#369bf1f9592d8ab89d712dced5cb81c7c5352649" @@ -6859,7 +7243,7 @@ object.pick@^1.3.0: dependencies: isobject "^3.0.1" -object.values@^1.1.0: +object.values@^1.1.0, object.values@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.1.tgz#68a99ecde356b7e9295a3c5e0ce31dc8c953de5e" integrity sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA== @@ -6909,6 +7293,18 @@ optionator@^0.8.1: type-check "~0.3.2" word-wrap "~1.2.3" +optionator@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" + integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== + dependencies: + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.3" + os-browserify@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" @@ -7582,6 +7978,11 @@ prebuild-install@^5.2.5: tunnel-agent "^0.6.0" which-pm-runs "^1.0.0" +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" @@ -7634,6 +8035,11 @@ process@^0.11.10: resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= +progress@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" + integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== + prompts@^2.0.1: version "2.3.2" resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.3.2.tgz#480572d89ecf39566d2bd3fe2c9fccb7c4c0b068" @@ -7642,7 +8048,7 @@ prompts@^2.0.1: kleur "^3.0.3" sisteransi "^1.0.4" -prop-types@^15.5.10, prop-types@^15.6.2: +prop-types@^15.5.10, prop-types@^15.6.2, prop-types@^15.7.2: version "15.7.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== @@ -7924,6 +8330,19 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" +regexp.prototype.flags@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz#7aba89b3c13a64509dabcf3ca8d9fbb9bdf5cb75" + integrity sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" + +regexpp@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" + integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== + regexpu-core@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-1.0.0.tgz#86a763f58ee4d7c2f6b102e4764050de7ed90c6b" @@ -8125,7 +8544,7 @@ resolve@^1.1.5, resolve@^1.12.0, resolve@^1.3.2: dependencies: path-parse "^1.0.6" -resolve@^1.10.0, resolve@^1.17.0, resolve@^1.8.1: +resolve@^1.10.0, resolve@^1.15.1, resolve@^1.17.0, resolve@^1.8.1: version "1.17.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== @@ -8168,6 +8587,13 @@ rgba-regex@^1.0.0: resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3" integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM= +rimraf@2.6.3: + version "2.6.3" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== + dependencies: + glob "^7.1.3" + rimraf@^2.6.2: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" @@ -8369,6 +8795,14 @@ shellwords@^0.1.1: resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww== +side-channel@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.2.tgz#df5d1abadb4e4bf4af1cd8852bf132d2f7876947" + integrity sha512-7rL9YlPHg7Ancea1S96Pa8/QWb4BtXL/TZvS6B8XFetGBeuhAsfmUspK6DokBeZ64+Kj9TCNRD/30pVz1BvQNA== + dependencies: + es-abstract "^1.17.0-next.1" + object-inspect "^1.7.0" + sigmund@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" @@ -8410,6 +8844,15 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== +slice-ansi@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" + integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== + dependencies: + ansi-styles "^3.2.0" + astral-regex "^1.0.0" + is-fullwidth-code-point "^2.0.0" + slice-ansi@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-3.0.0.tgz#31ddc10930a1b7e0b67b08c96c2f49b77a789787" @@ -8653,6 +9096,11 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" +string-natural-compare@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-3.0.1.tgz#7a42d58474454963759e8e8b7ae63d71c1e7fdf4" + integrity sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw== + string-width@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" @@ -8688,6 +9136,26 @@ string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.0" +string.prototype.matchall@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.2.tgz#48bb510326fb9fdeb6a33ceaa81a6ea04ef7648e" + integrity sha512-N/jp6O5fMf9os0JU3E72Qhf590RSRZU/ungsL/qJUYVTNv7hTG0P/dbPjxINVN9jpscu3nzYwKESU3P3RY5tOg== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0" + has-symbols "^1.0.1" + internal-slot "^1.0.2" + regexp.prototype.flags "^1.3.0" + side-channel "^1.0.2" + +string.prototype.trimend@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz#85812a6b847ac002270f5808146064c995fb6913" + integrity sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.5" + string.prototype.trimleft@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz#9bdb8ac6abd6d602b17a4ed321870d2f8dcefc74" @@ -8704,6 +9172,14 @@ string.prototype.trimright@^2.1.1: define-properties "^1.1.3" function-bind "^1.1.1" +string.prototype.trimstart@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz#14af6d9f34b053f7cfc89b72f8f2ee14b9039a54" + integrity sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.5" + string_decoder@^1.0.0, string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" @@ -8768,6 +9244,11 @@ strip-indent@^3.0.0: dependencies: min-indent "^1.0.0" +strip-json-comments@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.0.tgz#7638d31422129ecf4457440009fba03f9f9ac180" + integrity sha512-e6/d0eBu7gHtdCqFt0xJr642LdToM5/cN4Qb9DbHjVx1CP5RyeM+zH7pbecEmDv/lBqb0QH+6Uqq75rxFPkM0w== + strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" @@ -8847,6 +9328,16 @@ symbol-tree@^3.2.2, symbol-tree@^3.2.4: resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== +table@^5.2.3: + version "5.4.6" + resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" + integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== + dependencies: + ajv "^6.10.2" + lodash "^4.17.14" + slice-ansi "^2.1.0" + string-width "^3.0.0" + tar-fs@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.0.0.tgz#677700fc0c8b337a78bee3623fdc235f21d7afad" @@ -8903,6 +9394,11 @@ test-exclude@^6.0.0: glob "^7.1.4" minimatch "^3.0.4" +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + throat@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/throat/-/throat-5.0.0.tgz#c5199235803aad18754a667d659b5e72ce16764b" @@ -9024,11 +9520,23 @@ tr46@^2.0.2: dependencies: punycode "^2.1.1" +tslib@^1.8.1: + version "1.13.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043" + integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q== + tslib@^1.9.0: version "1.10.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== +tsutils@^3.17.1: + version "3.17.1" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759" + integrity sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g== + dependencies: + tslib "^1.8.1" + tty-browserify@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" @@ -9046,6 +9554,13 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + type-check@~0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" @@ -9241,6 +9756,11 @@ v8-compile-cache@^2.0.0: resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz#e14de37b31a6d194f5690d67efc4e7f6fc6ab30e" integrity sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g== +v8-compile-cache@^2.0.3: + version "2.1.1" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz#54bc3cdd43317bca91e35dcaf305b1a7237de745" + integrity sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ== + v8-to-istanbul@^4.1.3: version "4.1.4" resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-4.1.4.tgz#b97936f21c0e2d9996d4985e5c5156e9d4e49cd6" @@ -9402,7 +9922,7 @@ widest-line@^3.1.0: dependencies: string-width "^4.0.0" -word-wrap@~1.2.3: +word-wrap@^1.2.3, word-wrap@~1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== @@ -9440,6 +9960,13 @@ write-file-atomic@^3.0.0: signal-exit "^3.0.2" typedarray-to-buffer "^3.1.5" +write@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" + integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== + dependencies: + mkdirp "^0.5.1" + ws@^6.1.2, ws@^6.2.0: version "6.2.1" resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb" @@ -9462,6 +9989,13 @@ xmlchars@^2.1.1, xmlchars@^2.2.0: resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== +xregexp@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-4.3.0.tgz#7e92e73d9174a99a59743f67a4ce879a04b5ae50" + integrity sha512-7jXDIFXh5yJ/orPn4SXjuVrWWoi4Cr8jfV1eHv9CixKSbU+jY4mxfrBwAuDvupPNKpMUY+FeIqsVw/JLT9+B8g== + dependencies: + "@babel/runtime-corejs3" "^7.8.3" + xtend@^4.0.0, xtend@~4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" From f4edd14f623bb46efde39f50628326e20e658ab7 Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Mon, 29 Jun 2020 12:26:35 +0800 Subject: [PATCH 021/116] Implement new preprocessData and types to support new React marks (#20) --- src/constants.js | 4 + src/types.js | 81 + .../__snapshots__/preprocessData-test.js.snap | 1324 +++++++++++++++++ src/util/__tests__/preprocessData-test.js | 313 ++++ src/util/preprocessDataV2.js | 405 +++++ 5 files changed, 2127 insertions(+) create mode 100644 src/constants.js create mode 100644 src/util/__tests__/__snapshots__/preprocessData-test.js.snap create mode 100644 src/util/__tests__/preprocessData-test.js create mode 100644 src/util/preprocessDataV2.js diff --git a/src/constants.js b/src/constants.js new file mode 100644 index 0000000000000..6e40038f2f6ae --- /dev/null +++ b/src/constants.js @@ -0,0 +1,4 @@ +// @flow +// App constants + +export const REACT_TOTAL_NUM_LANES = 31; diff --git a/src/types.js b/src/types.js index e191d049bef33..03c972e7ab278 100644 --- a/src/types.js +++ b/src/types.js @@ -14,8 +14,10 @@ export type Return = Return_<*, T>; export type Milliseconds = number; +/** @deprecated */ export type ReactPriority = 'unscheduled' | 'high' | 'normal' | 'low'; +/** @deprecated */ export type ReactEventType = | 'schedule-render' | 'schedule-state-update' @@ -23,11 +25,14 @@ export type ReactEventType = export type ReactMeasureType = | 'commit' + // render-idle: A measure spanning the time when a render starts, through all + // yields and restarts, and ends when commit stops OR render is cancelled. | 'render-idle' | 'render' | 'layout-effects' | 'passive-effects'; +/** @deprecated */ export type ReactEvent = {| +type: ReactEventType, +priority: ReactPriority, @@ -39,6 +44,7 @@ export type ReactEvent = {| export type BatchUID = number; +/** @deprecated */ export type ReactMeasure = {| +type: ReactMeasureType, +priority: ReactPriority, @@ -48,12 +54,14 @@ export type ReactMeasure = {| +depth: number, |}; +/** @deprecated */ export type ReactProfilerDataPriority = {| events: Array, measures: Array, maxNestedMeasures: number, |}; +/** @deprecated */ export type ReactProfilerData = {| startTime: number, duration: number, @@ -64,11 +72,84 @@ export type ReactProfilerData = {| |}; export type ReactHoverContextInfo = {| + /** @deprecated */ event: ReactEvent | null, + /** @deprecated */ measure: ReactMeasure | null, + /** @deprecated */ priorityIndex: number | null, + /** @deprecated */ data: ReactProfilerData | null, flamechartNode: FlamechartFrame | null, |}; export type FlamechartData = Flamechart; + +export type ReactLane = number; + +type BaseReactEvent = {| + +componentName?: string, + +componentStack?: string, + +timestamp: Milliseconds, +|}; + +type BaseReactScheduleEvent = {| + ...BaseReactEvent, + +lanes: ReactLane[], +|}; +export type ReactScheduleRenderEvent = {| + ...BaseReactScheduleEvent, + type: 'schedule-render', +|}; +export type ReactScheduleStateUpdateEvent = {| + ...BaseReactScheduleEvent, + type: 'schedule-state-update', + isCascading: boolean, +|}; +export type ReactScheduleForceUpdateEvent = {| + ...BaseReactScheduleEvent, + type: 'schedule-force-update', + isCascading: boolean, +|}; + +type BaseReactSuspenseEvent = {| + ...BaseReactEvent, + id: string, +|}; +export type ReactSuspenseSuspendEvent = {| + ...BaseReactSuspenseEvent, + type: 'suspense-suspend', +|}; +export type ReactSuspenseResolvedEvent = {| + ...BaseReactSuspenseEvent, + type: 'suspense-resolved', +|}; +export type ReactSuspenseRejectedEvent = {| + ...BaseReactSuspenseEvent, + type: 'suspense-rejected', +|}; + +export type ReactEventV2 = + | ReactScheduleRenderEvent + | ReactScheduleStateUpdateEvent + | ReactScheduleForceUpdateEvent + | ReactSuspenseSuspendEvent + | ReactSuspenseResolvedEvent + | ReactSuspenseRejectedEvent; +export type ReactEventTypeV2 = $PropertyType; + +export type ReactMeasureV2 = {| + +type: ReactMeasureType, + +lanes: ReactLane[], + +timestamp: Milliseconds, + +duration: Milliseconds, + +batchUID: BatchUID, + +depth: number, +|}; + +export type ReactProfilerDataV2 = {| + startTime: number, + duration: number, + events: ReactEventV2[], + measures: ReactMeasureV2[], +|}; diff --git a/src/util/__tests__/__snapshots__/preprocessData-test.js.snap b/src/util/__tests__/__snapshots__/preprocessData-test.js.snap new file mode 100644 index 0000000000000..0e0f5e3b87343 --- /dev/null +++ b/src/util/__tests__/__snapshots__/preprocessData-test.js.snap @@ -0,0 +1,1324 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`preprocessData should process complete set of events (page load sample data) 1`] = ` +Object { + "duration": 2615.506, + "events": Array [ + Object { + "componentName": "Unknown", + "componentStack": "", + "lanes": Array [ + 9, + ], + "timestamp": 307.43, + "type": "schedule-render", + }, + Object { + "componentName": "ResourceButton", + "componentStack": " + at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) + at Suspense + at div + at div + at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) + at App", + "id": "0", + "timestamp": 687.702, + "type": "suspense-suspend", + }, + Object { + "componentName": "ResourceButton", + "componentStack": " + at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) + at Suspense + at div + at div + at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) + at App", + "id": "1", + "timestamp": 690.096, + "type": "suspense-suspend", + }, + Object { + "componentName": "ResourceButton", + "componentStack": " + at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) + at Suspense + at div + at div + at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) + at App", + "id": "2", + "timestamp": 691.911, + "type": "suspense-suspend", + }, + Object { + "componentName": "ResourceButton", + "componentStack": " + at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) + at Suspense + at div + at div + at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) + at App", + "id": "3", + "timestamp": 692.812, + "type": "suspense-suspend", + }, + Object { + "componentName": "ResourceButton", + "componentStack": " + at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) + at Suspense + at div + at div + at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) + at App", + "id": "4", + "timestamp": 693.559, + "type": "suspense-suspend", + }, + Object { + "componentName": "ResourceButton", + "componentStack": " + at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) + at Suspense + at div + at div + at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) + at App", + "id": "0", + "timestamp": 696.037, + "type": "suspense-suspend", + }, + Object { + "componentName": "ResourceButton", + "componentStack": " + at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) + at Suspense + at div + at div + at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) + at App", + "id": "1", + "timestamp": 696.558, + "type": "suspense-suspend", + }, + Object { + "componentName": "ResourceButton", + "componentStack": " + at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) + at Suspense + at div + at div + at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) + at App", + "id": "2", + "timestamp": 697.097, + "type": "suspense-suspend", + }, + Object { + "componentName": "ResourceButton", + "componentStack": " + at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) + at Suspense + at div + at div + at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) + at App", + "id": "3", + "timestamp": 697.639, + "type": "suspense-suspend", + }, + Object { + "componentName": "ResourceButton", + "componentStack": " + at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) + at Suspense + at div + at div + at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) + at App", + "id": "4", + "timestamp": 698.205, + "type": "suspense-suspend", + }, + Object { + "componentName": "ResourceButton", + "componentStack": " + at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) + at Suspense + at SuspenseList + at div + at div + at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) + at App", + "id": "0", + "timestamp": 700.692, + "type": "suspense-suspend", + }, + Object { + "componentName": "ForceUpdateDemo_ForceUpdateDemo", + "componentStack": " + at ForceUpdateDemo_ForceUpdateDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:18:98) + at App", + "isCascading": true, + "lanes": Array [ + 0, + ], + "timestamp": 708.795, + "type": "schedule-state-update", + }, + Object { + "componentName": "ResourceButton", + "componentStack": " + at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) + at Suspense + at div + at div + at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) + at App", + "id": "1", + "timestamp": 1824.279, + "type": "suspense-resolved", + }, + Object { + "componentName": "ResourceButton", + "componentStack": " + at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) + at Suspense + at div + at div + at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) + at App", + "id": "1", + "timestamp": 1824.731, + "type": "suspense-resolved", + }, + Object { + "componentName": "ResourceButton", + "componentStack": " + at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) + at Suspense + at div + at div + at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) + at App", + "id": "0", + "timestamp": 1826.523, + "type": "suspense-suspend", + }, + Object { + "componentName": "ResourceButton", + "componentStack": " + at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) + at Suspense + at div + at div + at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) + at App", + "id": "2", + "timestamp": 1827.168, + "type": "suspense-suspend", + }, + Object { + "componentName": "ResourceButton", + "componentStack": " + at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) + at Suspense + at div + at div + at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) + at App", + "id": "3", + "timestamp": 1827.52, + "type": "suspense-suspend", + }, + Object { + "componentName": "ResourceButton", + "componentStack": " + at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) + at Suspense + at div + at div + at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) + at App", + "id": "4", + "timestamp": 1827.862, + "type": "suspense-suspend", + }, + Object { + "componentName": "ResourceButton", + "componentStack": " + at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) + at Suspense + at div + at div + at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) + at App", + "id": "2", + "timestamp": 1895.606, + "type": "suspense-resolved", + }, + Object { + "componentName": "ResourceButton", + "componentStack": " + at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) + at Suspense + at div + at div + at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) + at App", + "id": "2", + "timestamp": 1895.899, + "type": "suspense-resolved", + }, + Object { + "componentName": "ResourceButton", + "componentStack": " + at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) + at Suspense + at div + at div + at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) + at App", + "id": "2", + "timestamp": 1896.215, + "type": "suspense-resolved", + }, + Object { + "componentName": "ResourceButton", + "componentStack": " + at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) + at Suspense + at div + at div + at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) + at App", + "id": "0", + "timestamp": 1897.173, + "type": "suspense-suspend", + }, + Object { + "componentName": "ResourceButton", + "componentStack": " + at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) + at Suspense + at div + at div + at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) + at App", + "id": "3", + "timestamp": 1897.995, + "type": "suspense-suspend", + }, + Object { + "componentName": "ResourceButton", + "componentStack": " + at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) + at Suspense + at div + at div + at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) + at App", + "id": "4", + "timestamp": 1898.323, + "type": "suspense-suspend", + }, + Object { + "componentName": "ResourceButton", + "componentStack": " + at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) + at Suspense + at div + at div + at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) + at App", + "id": "3", + "timestamp": 2009.63, + "type": "suspense-resolved", + }, + Object { + "componentName": "ResourceButton", + "componentStack": " + at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) + at Suspense + at div + at div + at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) + at App", + "id": "3", + "timestamp": 2009.879, + "type": "suspense-resolved", + }, + Object { + "componentName": "ResourceButton", + "componentStack": " + at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) + at Suspense + at div + at div + at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) + at App", + "id": "3", + "timestamp": 2010.303, + "type": "suspense-resolved", + }, + Object { + "componentName": "ResourceButton", + "componentStack": " + at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) + at Suspense + at div + at div + at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) + at App", + "id": "3", + "timestamp": 2010.521, + "type": "suspense-resolved", + }, + Object { + "componentName": "ResourceButton", + "componentStack": " + at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) + at Suspense + at div + at div + at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) + at App", + "id": "0", + "timestamp": 2011.436, + "type": "suspense-suspend", + }, + Object { + "componentName": "ResourceButton", + "componentStack": " + at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) + at Suspense + at div + at div + at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) + at App", + "id": "4", + "timestamp": 2012.527, + "type": "suspense-suspend", + }, + Object { + "componentName": "ResourceButton", + "componentStack": " + at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) + at Suspense + at div + at div + at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) + at App", + "id": "4", + "timestamp": 2408.944, + "type": "suspense-resolved", + }, + Object { + "componentName": "ResourceButton", + "componentStack": " + at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) + at Suspense + at div + at div + at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) + at App", + "id": "4", + "timestamp": 2409.252, + "type": "suspense-resolved", + }, + Object { + "componentName": "ResourceButton", + "componentStack": " + at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) + at Suspense + at div + at div + at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) + at App", + "id": "4", + "timestamp": 2409.599, + "type": "suspense-resolved", + }, + Object { + "componentName": "ResourceButton", + "componentStack": " + at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) + at Suspense + at div + at div + at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) + at App", + "id": "4", + "timestamp": 2409.844, + "type": "suspense-resolved", + }, + Object { + "componentName": "ResourceButton", + "componentStack": " + at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) + at Suspense + at div + at div + at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) + at App", + "id": "4", + "timestamp": 2410.092, + "type": "suspense-resolved", + }, + Object { + "componentName": "ResourceButton", + "componentStack": " + at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) + at Suspense + at div + at div + at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) + at App", + "id": "0", + "timestamp": 2411.129, + "type": "suspense-suspend", + }, + Object { + "componentName": "ResourceButton", + "componentStack": " + at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) + at Suspense + at div + at div + at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) + at App", + "id": "0", + "timestamp": 2608.543, + "type": "suspense-resolved", + }, + Object { + "componentName": "ResourceButton", + "componentStack": " + at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) + at Suspense + at div + at div + at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) + at App", + "id": "0", + "timestamp": 2608.844, + "type": "suspense-resolved", + }, + Object { + "componentName": "ResourceButton", + "componentStack": " + at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) + at Suspense + at SuspenseList + at div + at div + at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) + at App", + "id": "0", + "timestamp": 2609.092, + "type": "suspense-resolved", + }, + Object { + "componentName": "ResourceButton", + "componentStack": " + at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) + at Suspense + at div + at div + at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) + at App", + "id": "0", + "timestamp": 2609.399, + "type": "suspense-resolved", + }, + Object { + "componentName": "ResourceButton", + "componentStack": " + at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) + at Suspense + at div + at div + at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) + at App", + "id": "0", + "timestamp": 2609.647, + "type": "suspense-resolved", + }, + Object { + "componentName": "ResourceButton", + "componentStack": " + at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) + at Suspense + at div + at div + at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) + at App", + "id": "0", + "timestamp": 2609.903, + "type": "suspense-resolved", + }, + Object { + "componentName": "ResourceButton", + "componentStack": " + at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) + at Suspense + at div + at div + at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) + at App", + "id": "0", + "timestamp": 2610.157, + "type": "suspense-resolved", + }, + ], + "measures": Array [ + Object { + "batchUID": 0, + "depth": 0, + "duration": 402.58299999999997, + "lanes": Array [ + 9, + ], + "timestamp": 314.65, + "type": "render-idle", + }, + Object { + "batchUID": 0, + "depth": 0, + "duration": 5.235000000000014, + "lanes": Array [ + 9, + ], + "timestamp": 314.65, + "type": "render", + }, + Object { + "batchUID": 0, + "depth": 0, + "duration": 8.168000000000006, + "lanes": Array [ + 9, + ], + "timestamp": 327.065, + "type": "render", + }, + Object { + "batchUID": 0, + "depth": 0, + "duration": 4.988999999999976, + "lanes": Array [ + 9, + ], + "timestamp": 339.814, + "type": "render", + }, + Object { + "batchUID": 0, + "depth": 0, + "duration": 6.46999999999997, + "lanes": Array [ + 9, + ], + "timestamp": 387.124, + "type": "render", + }, + Object { + "batchUID": 0, + "depth": 0, + "duration": 6.632999999999981, + "lanes": Array [ + 9, + ], + "timestamp": 400.843, + "type": "render", + }, + Object { + "batchUID": 0, + "depth": 0, + "duration": 9.890000000000043, + "lanes": Array [ + 9, + ], + "timestamp": 414.407, + "type": "render", + }, + Object { + "batchUID": 0, + "depth": 0, + "duration": 7.859000000000037, + "lanes": Array [ + 9, + ], + "timestamp": 427.417, + "type": "render", + }, + Object { + "batchUID": 0, + "depth": 0, + "duration": 7.260999999999967, + "lanes": Array [ + 9, + ], + "timestamp": 436.023, + "type": "render", + }, + Object { + "batchUID": 0, + "depth": 0, + "duration": 7.701000000000022, + "lanes": Array [ + 9, + ], + "timestamp": 443.575, + "type": "render", + }, + Object { + "batchUID": 0, + "depth": 0, + "duration": 7.793000000000006, + "lanes": Array [ + 9, + ], + "timestamp": 451.498, + "type": "render", + }, + Object { + "batchUID": 0, + "depth": 0, + "duration": 7.7070000000000505, + "lanes": Array [ + 9, + ], + "timestamp": 459.542, + "type": "render", + }, + Object { + "batchUID": 0, + "depth": 0, + "duration": 7.406999999999982, + "lanes": Array [ + 9, + ], + "timestamp": 468.909, + "type": "render", + }, + Object { + "batchUID": 0, + "depth": 0, + "duration": 7.649000000000001, + "lanes": Array [ + 9, + ], + "timestamp": 476.651, + "type": "render", + }, + Object { + "batchUID": 0, + "depth": 0, + "duration": 7.73599999999999, + "lanes": Array [ + 9, + ], + "timestamp": 484.572, + "type": "render", + }, + Object { + "batchUID": 0, + "depth": 0, + "duration": 7.696000000000026, + "lanes": Array [ + 9, + ], + "timestamp": 492.616, + "type": "render", + }, + Object { + "batchUID": 0, + "depth": 0, + "duration": 7.701000000000022, + "lanes": Array [ + 9, + ], + "timestamp": 500.604, + "type": "render", + }, + Object { + "batchUID": 0, + "depth": 0, + "duration": 7.555000000000007, + "lanes": Array [ + 9, + ], + "timestamp": 508.719, + "type": "render", + }, + Object { + "batchUID": 0, + "depth": 0, + "duration": 7.789999999999964, + "lanes": Array [ + 9, + ], + "timestamp": 516.552, + "type": "render", + }, + Object { + "batchUID": 0, + "depth": 0, + "duration": 7.616999999999962, + "lanes": Array [ + 9, + ], + "timestamp": 524.711, + "type": "render", + }, + Object { + "batchUID": 0, + "depth": 0, + "duration": 7.241999999999962, + "lanes": Array [ + 9, + ], + "timestamp": 533.063, + "type": "render", + }, + Object { + "batchUID": 0, + "depth": 0, + "duration": 7.819000000000074, + "lanes": Array [ + 9, + ], + "timestamp": 542.463, + "type": "render", + }, + Object { + "batchUID": 0, + "depth": 0, + "duration": 9.269999999999982, + "lanes": Array [ + 9, + ], + "timestamp": 551.024, + "type": "render", + }, + Object { + "batchUID": 0, + "depth": 0, + "duration": 7.7579999999999245, + "lanes": Array [ + 9, + ], + "timestamp": 560.542, + "type": "render", + }, + Object { + "batchUID": 0, + "depth": 0, + "duration": 7.7349999999999, + "lanes": Array [ + 9, + ], + "timestamp": 568.57, + "type": "render", + }, + Object { + "batchUID": 0, + "depth": 0, + "duration": 7.7299999999999045, + "lanes": Array [ + 9, + ], + "timestamp": 576.58, + "type": "render", + }, + Object { + "batchUID": 0, + "depth": 0, + "duration": 7.697000000000003, + "lanes": Array [ + 9, + ], + "timestamp": 584.591, + "type": "render", + }, + Object { + "batchUID": 0, + "depth": 0, + "duration": 7.714999999999918, + "lanes": Array [ + 9, + ], + "timestamp": 592.589, + "type": "render", + }, + Object { + "batchUID": 0, + "depth": 0, + "duration": 7.761000000000081, + "lanes": Array [ + 9, + ], + "timestamp": 600.569, + "type": "render", + }, + Object { + "batchUID": 0, + "depth": 0, + "duration": 7.617999999999938, + "lanes": Array [ + 9, + ], + "timestamp": 608.681, + "type": "render", + }, + Object { + "batchUID": 0, + "depth": 0, + "duration": 7.738000000000056, + "lanes": Array [ + 9, + ], + "timestamp": 616.558, + "type": "render", + }, + Object { + "batchUID": 0, + "depth": 0, + "duration": 7.738999999999919, + "lanes": Array [ + 9, + ], + "timestamp": 624.566, + "type": "render", + }, + Object { + "batchUID": 0, + "depth": 0, + "duration": 7.731999999999971, + "lanes": Array [ + 9, + ], + "timestamp": 632.551, + "type": "render", + }, + Object { + "batchUID": 0, + "depth": 0, + "duration": 7.713000000000079, + "lanes": Array [ + 9, + ], + "timestamp": 640.569, + "type": "render", + }, + Object { + "batchUID": 0, + "depth": 0, + "duration": 7.3700000000000045, + "lanes": Array [ + 9, + ], + "timestamp": 648.931, + "type": "render", + }, + Object { + "batchUID": 0, + "depth": 0, + "duration": 7.73599999999999, + "lanes": Array [ + 9, + ], + "timestamp": 656.545, + "type": "render", + }, + Object { + "batchUID": 0, + "depth": 0, + "duration": 7.729000000000042, + "lanes": Array [ + 9, + ], + "timestamp": 664.55, + "type": "render", + }, + Object { + "batchUID": 0, + "depth": 0, + "duration": 7.908999999999992, + "lanes": Array [ + 9, + ], + "timestamp": 672.563, + "type": "render", + }, + Object { + "batchUID": 0, + "depth": 0, + "duration": 7.6159999999999854, + "lanes": Array [ + 9, + ], + "timestamp": 680.696, + "type": "render", + }, + Object { + "batchUID": 0, + "depth": 0, + "duration": 5.334999999999923, + "lanes": Array [ + 9, + ], + "timestamp": 688.802, + "type": "render", + }, + Object { + "batchUID": 0, + "depth": 0, + "duration": 5.5890000000000555, + "lanes": Array [ + 9, + ], + "timestamp": 694.309, + "type": "render", + }, + Object { + "batchUID": 0, + "depth": 0, + "duration": 1.58400000000006, + "lanes": Array [ + 9, + ], + "timestamp": 700.141, + "type": "render", + }, + Object { + "batchUID": 0, + "depth": 0, + "duration": 14.551999999999907, + "lanes": Array [ + 9, + ], + "timestamp": 702.681, + "type": "commit", + }, + Object { + "batchUID": 0, + "depth": 1, + "duration": 2.689000000000078, + "lanes": Array [ + 9, + ], + "timestamp": 706.593, + "type": "layout-effects", + }, + Object { + "batchUID": 1, + "depth": 1, + "duration": 3.55600000000004, + "lanes": Array [ + 0, + ], + "timestamp": 713.461, + "type": "render-idle", + }, + Object { + "batchUID": 1, + "depth": 1, + "duration": 2.2169999999999845, + "lanes": Array [ + 0, + ], + "timestamp": 713.461, + "type": "render", + }, + Object { + "batchUID": 1, + "depth": 1, + "duration": 1.3120000000000118, + "lanes": Array [ + 0, + ], + "timestamp": 715.705, + "type": "commit", + }, + Object { + "batchUID": 1, + "depth": 2, + "duration": 0.020999999999958163, + "lanes": Array [ + 0, + ], + "timestamp": 716.624, + "type": "layout-effects", + }, + Object { + "batchUID": 2, + "depth": 0, + "duration": 6.119000000000142, + "lanes": Array [ + 10, + ], + "timestamp": 1825.399, + "type": "render-idle", + }, + Object { + "batchUID": 2, + "depth": 0, + "duration": 3.43300000000022, + "lanes": Array [ + 10, + ], + "timestamp": 1825.399, + "type": "render", + }, + Object { + "batchUID": 2, + "depth": 0, + "duration": 2.588999999999942, + "lanes": Array [ + 10, + ], + "timestamp": 1828.929, + "type": "commit", + }, + Object { + "batchUID": 2, + "depth": 1, + "duration": 0.020999999999958163, + "lanes": Array [ + 10, + ], + "timestamp": 1830.962, + "type": "layout-effects", + }, + Object { + "batchUID": 3, + "depth": 0, + "duration": 4.116999999999962, + "lanes": Array [ + 11, + ], + "timestamp": 1896.355, + "type": "render-idle", + }, + Object { + "batchUID": 3, + "depth": 0, + "duration": 2.6679999999998927, + "lanes": Array [ + 11, + ], + "timestamp": 1896.355, + "type": "render", + }, + Object { + "batchUID": 3, + "depth": 0, + "duration": 1.4200000000000728, + "lanes": Array [ + 11, + ], + "timestamp": 1899.052, + "type": "commit", + }, + Object { + "batchUID": 3, + "depth": 1, + "duration": 0.01999999999998181, + "lanes": Array [ + 11, + ], + "timestamp": 1900.121, + "type": "layout-effects", + }, + Object { + "batchUID": 4, + "depth": 0, + "duration": 3.768000000000029, + "lanes": Array [ + 12, + ], + "timestamp": 2010.718, + "type": "render-idle", + }, + Object { + "batchUID": 4, + "depth": 0, + "duration": 2.438999999999851, + "lanes": Array [ + 12, + ], + "timestamp": 2010.718, + "type": "render", + }, + Object { + "batchUID": 4, + "depth": 0, + "duration": 1.2580000000000382, + "lanes": Array [ + 12, + ], + "timestamp": 2013.228, + "type": "commit", + }, + Object { + "batchUID": 4, + "depth": 1, + "duration": 0.027000000000043656, + "lanes": Array [ + 12, + ], + "timestamp": 2014.288, + "type": "layout-effects", + }, + Object { + "batchUID": 5, + "depth": 0, + "duration": 3.8899999999998727, + "lanes": Array [ + 13, + ], + "timestamp": 2410.326, + "type": "render-idle", + }, + Object { + "batchUID": 5, + "depth": 0, + "duration": 2.3099999999999454, + "lanes": Array [ + 13, + ], + "timestamp": 2410.326, + "type": "render", + }, + Object { + "batchUID": 5, + "depth": 0, + "duration": 1.5209999999997308, + "lanes": Array [ + 13, + ], + "timestamp": 2412.695, + "type": "commit", + }, + Object { + "batchUID": 5, + "depth": 1, + "duration": 0.01999999999998181, + "lanes": Array [ + 13, + ], + "timestamp": 2413.892, + "type": "layout-effects", + }, + Object { + "batchUID": 6, + "depth": 0, + "duration": 5.942999999999756, + "lanes": Array [ + 14, + ], + "timestamp": 2610.309, + "type": "render-idle", + }, + Object { + "batchUID": 6, + "depth": 0, + "duration": 3.424999999999727, + "lanes": Array [ + 14, + ], + "timestamp": 2610.309, + "type": "render", + }, + Object { + "batchUID": 6, + "depth": 0, + "duration": 2.4470000000001164, + "lanes": Array [ + 14, + ], + "timestamp": 2613.805, + "type": "commit", + }, + Object { + "batchUID": 6, + "depth": 1, + "duration": 0.027000000000043656, + "lanes": Array [ + 14, + ], + "timestamp": 2615.479, + "type": "layout-effects", + }, + ], + "startTime": 8993749139, +} +`; + +exports[`preprocessData should process forced update event 1`] = ` +Object { + "duration": 3.988, + "events": Array [ + Object { + "componentName": "ForceUpdateDemo_ForceUpdateDemo", + "componentStack": " + at ForceUpdateDemo_ForceUpdateDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:18:98) + at App", + "isCascading": false, + "lanes": Array [ + 4, + ], + "timestamp": 0, + "type": "schedule-force-update", + }, + ], + "measures": Array [ + Object { + "batchUID": 0, + "depth": 0, + "duration": 2.191, + "lanes": Array [ + 4, + ], + "timestamp": 1.915, + "type": "render-idle", + }, + Object { + "batchUID": 0, + "depth": 0, + "duration": 0.9769999999999999, + "lanes": Array [ + 4, + ], + "timestamp": 1.915, + "type": "render", + }, + Object { + "batchUID": 0, + "depth": 0, + "duration": 1.1669999999999998, + "lanes": Array [ + 4, + ], + "timestamp": 2.939, + "type": "commit", + }, + Object { + "batchUID": 0, + "depth": 1, + "duration": 0.017999999999999794, + "lanes": Array [ + 4, + ], + "timestamp": 3.97, + "type": "layout-effects", + }, + ], + "startTime": 40806988231, +} +`; diff --git a/src/util/__tests__/preprocessData-test.js b/src/util/__tests__/preprocessData-test.js new file mode 100644 index 0000000000000..b66e8a80165a9 --- /dev/null +++ b/src/util/__tests__/preprocessData-test.js @@ -0,0 +1,313 @@ +'use strict'; + +import preprocessData, { + getLanesFromTransportDecimalBitmask, +} from '../preprocessDataV2'; +import { REACT_TOTAL_NUM_LANES } from '../../constants'; + +describe(getLanesFromTransportDecimalBitmask, () => { + it('should return array of lane numbers from bitmask string', () => { + expect(getLanesFromTransportDecimalBitmask('1')).toEqual([0]); + expect(getLanesFromTransportDecimalBitmask('512')).toEqual([9]); + expect(getLanesFromTransportDecimalBitmask('3')).toEqual([0, 1]); + expect(getLanesFromTransportDecimalBitmask('1234')).toEqual([ + 1, + 4, + 6, + 7, + 10, + ]); // 2 + 16 + 64 + 128 + 1024 + expect( + getLanesFromTransportDecimalBitmask('1073741824') // 0b1000000000000000000000000000000 + ).toEqual([30]); + expect( + getLanesFromTransportDecimalBitmask('2147483647') // 0b1111111111111111111111111111111 + ).toEqual(Array.from(Array(31).keys())); + }); + + it('should return empty array if laneBitmaskString is not a bitmask', () => { + expect(getLanesFromTransportDecimalBitmask('')).toEqual([]); + expect(getLanesFromTransportDecimalBitmask('hello')).toEqual([]); + expect(getLanesFromTransportDecimalBitmask('-1')).toEqual([]); + expect(getLanesFromTransportDecimalBitmask('-0')).toEqual([]); + }); + + it('should ignore lanes outside REACT_TOTAL_NUM_LANES', () => { + // Sanity check; this test may need to be updated when the no. of fiber + // lanes are changed. + expect(REACT_TOTAL_NUM_LANES).toBe(31); + + expect( + getLanesFromTransportDecimalBitmask( + '4294967297' // 2^32 + 1 + ) + ).toEqual([0]); + }); +}); + +describe(preprocessData, () => { + it('should return empty data given an empty timeline', () => { + const input = []; + expect(preprocessData([])).toEqual({ + startTime: 0, + duration: 0, + events: [], + measures: [], + }); + }); + + it('should return empty data given a timeline with no React scheduling profiling marks', () => { + // prettier-ignore + const input = [ + {"pid":57632,"tid":38659,"ts":874860756135,"ph":"X","cat":"disabled-by-default-devtools.timeline","name":"RunTask","dur":18,"tdur":19,"tts":8700284918,"args":{}}, + {"pid":57632,"tid":38659,"ts":874860756158,"ph":"X","cat":"disabled-by-default-devtools.timeline","name":"RunTask","dur":30,"tdur":30,"tts":8700284941,"args":{}}, + {"pid":57632,"tid":38659,"ts":874860756192,"ph":"X","cat":"disabled-by-default-devtools.timeline","name":"RunTask","dur":21,"tdur":20,"tts":8700284976,"args":{}}, + {"pid":57632,"tid":38659,"ts":874860756216,"ph":"X","cat":"disabled-by-default-devtools.timeline","name":"RunTask","dur":6,"tdur":5,"tts":8700285000,"args":{}}, + {"pid":57632,"tid":38659,"ts":874860756224,"ph":"X","cat":"disabled-by-default-devtools.timeline","name":"RunTask","dur":7,"tdur":6,"tts":8700285008,"args":{}}, + {"pid":57632,"tid":38659,"ts":874860756233,"ph":"X","cat":"disabled-by-default-devtools.timeline","name":"RunTask","dur":5,"tdur":4,"tts":8700285017,"args":{}}, + ] + + expect(preprocessData(input)).toEqual({ + startTime: 874860756135, + duration: 0, + events: [], + measures: [], + }); + }); + + it('should throw if unrecognized React mark is encountered', () => { + expect(() => + preprocessData([ + // prettier-ignore + {"args":{"data":{"navigationId":"E082C30FBDA3ACEE0E7B5FD75F8B7F0D"}},"cat":"blink.user_timing","name":"--there-are-four-lights","ph":"R","pid":17232,"tid":13628,"ts":264686513020,"tts":4082554}, + ]) + ).toThrow(); + }); + + it('should throw if events and measures are incomplete', () => { + const error = jest.spyOn(console, 'error'); + preprocessData([ + // prettier-ignore + {"args":{"data":{"navigationId":"1065756F5FDAD64BE45CA86B0BBC1F8B"}},"cat":"blink.user_timing","name":"--render-start-8","ph":"R","pid":1852,"tid":12484,"ts":42351664678,"tts":1512475}, + ]); + expect(error).toHaveBeenCalled(); + }); + + it('should throw if work is completed without being started', () => { + const error = jest.spyOn(console, 'error'); + preprocessData([ + // prettier-ignore + {"args":{"data":{"navigationId":"E082C30FBDA3ACEE0E7B5FD75F8B7F0D"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":17232,"tid":13628,"ts":264686513020,"tts":4082554}, + ]); + expect(error).toHaveBeenCalled(); + + // TODO: add others + }); + + it('should process complete set of events (page load sample data)', () => { + expect( + // prettier-ignore + preprocessData([ + {"args":{"data":{"documentLoaderURL":"https://concurrent-demo.now.sh/","isLoadingMainFrame":true,"navigationId":"43BC238A4FB7548146D3CD739C9C9434"},"frame":"FD65D9AFD04B1295CEA36B883F0FA82F"},"cat":"blink.user_timing","name":"navigationStart","ph":"R","pid":9312,"tid":10252,"ts":8993749139,"tts":1646191}, + {"args":{"frame":"FD65D9AFD04B1295CEA36B883F0FA82F"},"cat":"blink.user_timing","name":"fetchStart","ph":"R","pid":9312,"tid":10252,"ts":8993751576,"tts":1646197}, + {"args":{},"cat":"blink.user_timing","name":"requestStart","ph":"R","pid":9312,"tid":10252,"ts":8993757325,"tts":1612760}, + {"args":{"frame":"FD65D9AFD04B1295CEA36B883F0FA82F"},"cat":"blink.user_timing","name":"responseEnd","ph":"R","pid":9312,"tid":10252,"ts":8993762841,"tts":1652151}, + {"args":{"frame":"FD65D9AFD04B1295CEA36B883F0FA82F"},"cat":"blink.user_timing","name":"unloadEventStart","ph":"R","pid":9312,"tid":10252,"ts":8993777756,"tts":1646416}, + {"args":{"frame":"FD65D9AFD04B1295CEA36B883F0FA82F"},"cat":"blink.user_timing","name":"unloadEventEnd","ph":"R","pid":9312,"tid":10252,"ts":8993818104,"tts":1646419}, + {"args":{"frame":"FD65D9AFD04B1295CEA36B883F0FA82F"},"cat":"blink.user_timing,rail","name":"domLoading","ph":"R","pid":9312,"tid":10252,"ts":8993820215,"tts":1647488}, + {"args":{},"cat":"blink.user_timing","name":"requestStart","ph":"R","pid":9312,"tid":10252,"ts":8993886145,"tts":1771277}, + {"args":{},"cat":"blink.user_timing","name":"requestStart","ph":"R","pid":9312,"tid":10252,"ts":8993886881,"tts":1778953}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--schedule-render-Unknown-512-","ph":"R","pid":9312,"tid":10252,"ts":8994056569,"tts":1816966}, + {"args":{"frame":"FD65D9AFD04B1295CEA36B883F0FA82F"},"cat":"blink.user_timing,rail","name":"domInteractive","ph":"R","pid":9312,"tid":10252,"ts":8994058638,"tts":1818851}, + {"args":{"frame":"FD65D9AFD04B1295CEA36B883F0FA82F"},"cat":"blink.user_timing,rail","name":"domContentLoadedEventStart","ph":"R","pid":9312,"tid":10252,"ts":8994058898,"tts":1819078}, + {"args":{"frame":"FD65D9AFD04B1295CEA36B883F0FA82F"},"cat":"blink.user_timing,rail","name":"domContentLoadedEventEnd","ph":"R","pid":9312,"tid":10252,"ts":8994060045,"tts":1820100}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994063789,"tts":1823183}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994069024,"tts":1826507}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994076204,"tts":1830657}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994084372,"tts":1837590}, + {"args":{"frame":"FD65D9AFD04B1295CEA36B883F0FA82F"},"cat":"blink.user_timing,rail","name":"domComplete","ph":"R","pid":9312,"tid":10252,"ts":8994085517,"tts":1838615}, + {"args":{"frame":"FD65D9AFD04B1295CEA36B883F0FA82F"},"cat":"blink.user_timing","name":"loadEventStart","ph":"R","pid":9312,"tid":10252,"ts":8994085552,"tts":1838649}, + {"args":{"frame":"FD65D9AFD04B1295CEA36B883F0FA82F"},"cat":"blink.user_timing","name":"loadEventEnd","ph":"R","pid":9312,"tid":10252,"ts":8994086738,"tts":1839690}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994088953,"tts":1840749}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994093942,"tts":1844455}, + {"args":{},"cat":"blink.user_timing","name":"requestStart","ph":"R","pid":9312,"tid":10252,"ts":8994119825,"tts":1877483}, + {"args":{},"cat":"blink.user_timing","name":"requestStart","ph":"R","pid":9312,"tid":10252,"ts":8994122516,"tts":1886344}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994136263,"tts":1871212}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994142733,"tts":1875838}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994149982,"tts":1880208}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994156615,"tts":1885309}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994163546,"tts":1887453}, + {"args":{},"cat":"blink.user_timing","name":"requestStart","ph":"R","pid":9312,"tid":10252,"ts":8994166081,"tts":1895751}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994173436,"tts":1894442}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994176556,"tts":1897176}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994184415,"tts":1904263}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994185162,"tts":1904938}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994192423,"tts":1910624}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994192714,"tts":1910872}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994200415,"tts":1917859}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994200637,"tts":1918062}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994208430,"tts":1924894}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994208681,"tts":1925124}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994216388,"tts":1932117}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994218048,"tts":1933622}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994225455,"tts":1940076}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994225790,"tts":1940391}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994233439,"tts":1947224}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994233711,"tts":1947473}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994241447,"tts":1954160}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994241755,"tts":1954426}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994249451,"tts":1961213}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994249743,"tts":1961494}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994257444,"tts":1968141}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994257858,"tts":1968525}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994265413,"tts":1975172}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994265691,"tts":1975416}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994273481,"tts":1981826}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994273850,"tts":1982112}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994281467,"tts":1988537}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994282202,"tts":1988894}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994289444,"tts":1994103}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994291602,"tts":1995165}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994299421,"tts":2000342}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994300163,"tts":2001009}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994309433,"tts":2005662}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994309681,"tts":2005897}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994317439,"tts":2012641}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994317709,"tts":2012890}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994325444,"tts":2019235}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994325719,"tts":2019477}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994333449,"tts":2026367}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994333730,"tts":2026617}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994341427,"tts":2033147}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994341728,"tts":2033411}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994349443,"tts":2040163}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994349708,"tts":2040409}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994357469,"tts":2047136}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994357820,"tts":2047465}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994365438,"tts":2054203}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994365697,"tts":2054434}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994373435,"tts":2061259}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994373705,"tts":2061502}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994381444,"tts":2068300}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994381690,"tts":2068529}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994389422,"tts":2075272}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994389708,"tts":2075518}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994397421,"tts":2082156}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994398070,"tts":2082726}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994405440,"tts":2088860}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994405684,"tts":2089091}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994413420,"tts":2095780}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994413689,"tts":2096021}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994421418,"tts":2102791}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994421702,"tts":2103047}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994429611,"tts":2110142}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994429835,"tts":2110349}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-ResourceButton-0-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994436841,"tts":2115594}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994437451,"tts":2116087}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994437941,"tts":2116287}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-ResourceButton-1-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994439235,"tts":2117153}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-ResourceButton-2-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994441050,"tts":2118088}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-ResourceButton-3-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994441951,"tts":2118783}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-ResourceButton-4-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994442698,"tts":2119371}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994443276,"tts":2119875}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994443448,"tts":2120040}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-ResourceButton-0-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994445176,"tts":2121499}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-ResourceButton-1-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994445697,"tts":2121968}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-ResourceButton-2-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994446236,"tts":2122460}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-ResourceButton-3-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994446778,"tts":2122951}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-ResourceButton-4-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994447344,"tts":2123444}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994449037,"tts":2124925}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994449280,"tts":2125142}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-ResourceButton-0-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at SuspenseList\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994449831,"tts":2125639}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-stop","ph":"R","pid":9312,"tid":10252,"ts":8994450864,"tts":2126555}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--commit-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994451820,"tts":2127417}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--layout-effects-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994455732,"tts":2130777}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--schedule-state-update-ForceUpdateDemo_ForceUpdateDemo-1-\n at ForceUpdateDemo_ForceUpdateDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:18:98)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994457934,"tts":2132671}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--layout-effects-stop","ph":"R","pid":9312,"tid":10252,"ts":8994458421,"tts":2133089}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-1","ph":"R","pid":9312,"tid":10252,"ts":8994462600,"tts":2136847}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-stop","ph":"R","pid":9312,"tid":10252,"ts":8994464817,"tts":2138817}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--commit-start-1","ph":"R","pid":9312,"tid":10252,"ts":8994464844,"tts":2138843}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--layout-effects-start-1","ph":"R","pid":9312,"tid":10252,"ts":8994465763,"tts":2139664}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--layout-effects-stop","ph":"R","pid":9312,"tid":10252,"ts":8994465784,"tts":2139686}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--commit-stop","ph":"R","pid":9312,"tid":10252,"ts":8994466156,"tts":2140023}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--commit-stop","ph":"R","pid":9312,"tid":10252,"ts":8994466372,"tts":2140208}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-ResourceButton-1-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995573418,"tts":2205582}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-ResourceButton-1-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995573870,"tts":2205980}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-1024","ph":"R","pid":9312,"tid":10252,"ts":8995574538,"tts":2206568}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-ResourceButton-0-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995575662,"tts":2207534}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-ResourceButton-2-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995576307,"tts":2208142}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-ResourceButton-3-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995576659,"tts":2208445}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-ResourceButton-4-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995577001,"tts":2208736}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-stop","ph":"R","pid":9312,"tid":10252,"ts":8995577971,"tts":2209602}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--commit-start-1024","ph":"R","pid":9312,"tid":10252,"ts":8995578068,"tts":2209689}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--layout-effects-start-1024","ph":"R","pid":9312,"tid":10252,"ts":8995580101,"tts":2211495}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--layout-effects-stop","ph":"R","pid":9312,"tid":10252,"ts":8995580122,"tts":2211515}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--commit-stop","ph":"R","pid":9312,"tid":10252,"ts":8995580657,"tts":2211995}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-ResourceButton-2-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995644745,"tts":2217336}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-ResourceButton-2-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995645038,"tts":2217571}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-ResourceButton-2-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995645354,"tts":2217861}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-2048","ph":"R","pid":9312,"tid":10252,"ts":8995645494,"tts":2217999}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-ResourceButton-0-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995646312,"tts":2218721}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-ResourceButton-3-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995647134,"tts":2219450}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-ResourceButton-4-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995647462,"tts":2219740}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-stop","ph":"R","pid":9312,"tid":10252,"ts":8995648162,"tts":2220335}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--commit-start-2048","ph":"R","pid":9312,"tid":10252,"ts":8995648191,"tts":2220363}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--layout-effects-start-2048","ph":"R","pid":9312,"tid":10252,"ts":8995649260,"tts":2221320}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--layout-effects-stop","ph":"R","pid":9312,"tid":10252,"ts":8995649280,"tts":2221340}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--commit-stop","ph":"R","pid":9312,"tid":10252,"ts":8995649611,"tts":2221636}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-ResourceButton-3-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995758769,"tts":2228839}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-ResourceButton-3-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995759018,"tts":2229064}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-ResourceButton-3-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995759442,"tts":2229424}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-ResourceButton-3-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995759660,"tts":2229627}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-4096","ph":"R","pid":9312,"tid":10252,"ts":8995759857,"tts":2229803}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-ResourceButton-0-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995760575,"tts":2230456}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-ResourceButton-4-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995761666,"tts":2231399}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-stop","ph":"R","pid":9312,"tid":10252,"ts":8995762296,"tts":2231965}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--commit-start-4096","ph":"R","pid":9312,"tid":10252,"ts":8995762367,"tts":2232017}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--layout-effects-start-4096","ph":"R","pid":9312,"tid":10252,"ts":8995763427,"tts":2232966}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--layout-effects-stop","ph":"R","pid":9312,"tid":10252,"ts":8995763454,"tts":2232993}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--commit-stop","ph":"R","pid":9312,"tid":10252,"ts":8995763625,"tts":2233154}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-ResourceButton-4-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996158083,"tts":2252466}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-ResourceButton-4-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996158391,"tts":2252730}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-ResourceButton-4-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996158738,"tts":2253038}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-ResourceButton-4-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996158983,"tts":2253239}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-ResourceButton-4-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996159231,"tts":2253447}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-8192","ph":"R","pid":9312,"tid":10252,"ts":8996159465,"tts":2253624}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-ResourceButton-0-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996160268,"tts":2254312}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-stop","ph":"R","pid":9312,"tid":10252,"ts":8996161775,"tts":2255670}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--commit-start-8192","ph":"R","pid":9312,"tid":10252,"ts":8996161834,"tts":2255716}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--layout-effects-start-8192","ph":"R","pid":9312,"tid":10252,"ts":8996163031,"tts":2256754}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--layout-effects-stop","ph":"R","pid":9312,"tid":10252,"ts":8996163051,"tts":2256773}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--commit-stop","ph":"R","pid":9312,"tid":10252,"ts":8996163355,"tts":2257045}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-ResourceButton-0-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996357682,"tts":2267920}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-ResourceButton-0-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996357983,"tts":2268179}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-ResourceButton-0-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at SuspenseList\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996358231,"tts":2268389}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-ResourceButton-0-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996358538,"tts":2268679}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-ResourceButton-0-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996358786,"tts":2268867}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-ResourceButton-0-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996359042,"tts":2269066}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-ResourceButton-0-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996359296,"tts":2269264}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-16384","ph":"R","pid":9312,"tid":10252,"ts":8996359448,"tts":2269412}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-stop","ph":"R","pid":9312,"tid":10252,"ts":8996362873,"tts":2272363}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--commit-start-16384","ph":"R","pid":9312,"tid":10252,"ts":8996362944,"tts":2272420}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--layout-effects-start-16384","ph":"R","pid":9312,"tid":10252,"ts":8996364618,"tts":2273869}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--layout-effects-stop","ph":"R","pid":9312,"tid":10252,"ts":8996364645,"tts":2273895}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--commit-stop","ph":"R","pid":9312,"tid":10252,"ts":8996365391,"tts":2274547}, + ]) + ).toMatchSnapshot(); + }); + + it('should process forced update event', () => { + expect( + // prettier-ignore + preprocessData([ + {"args":{"data":{"navigationId":"1065756F5FDAD64BE45CA86B0BBC1F8B"}},"cat":"blink.user_timing","name":"--schedule-forced-update-ForceUpdateDemo_ForceUpdateDemo-16-\n at ForceUpdateDemo_ForceUpdateDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:18:98)\n at App","ph":"R","pid":1852,"tid":12484,"ts":40806988231,"tts":1037762}, + {"args":{"data":{"navigationId":"1065756F5FDAD64BE45CA86B0BBC1F8B"}},"cat":"blink.user_timing","name":"--render-start-16","ph":"R","pid":1852,"tid":12484,"ts":40806990146,"tts":1038890}, + {"args":{"data":{"navigationId":"1065756F5FDAD64BE45CA86B0BBC1F8B"}},"cat":"blink.user_timing","name":"--render-stop","ph":"R","pid":1852,"tid":12484,"ts":40806991123,"tts":1039401}, + {"args":{"data":{"navigationId":"1065756F5FDAD64BE45CA86B0BBC1F8B"}},"cat":"blink.user_timing","name":"--commit-start-16","ph":"R","pid":1852,"tid":12484,"ts":40806991170,"tts":1039447}, + {"args":{"data":{"navigationId":"1065756F5FDAD64BE45CA86B0BBC1F8B"}},"cat":"blink.user_timing","name":"--layout-effects-start-16","ph":"R","pid":1852,"tid":12484,"ts":40806992201,"tts":1040023}, + {"args":{"data":{"navigationId":"1065756F5FDAD64BE45CA86B0BBC1F8B"}},"cat":"blink.user_timing","name":"--layout-effects-stop","ph":"R","pid":1852,"tid":12484,"ts":40806992219,"tts":1040041}, + {"args":{"data":{"navigationId":"1065756F5FDAD64BE45CA86B0BBC1F8B"}},"cat":"blink.user_timing","name":"--commit-stop","ph":"R","pid":1852,"tid":12484,"ts":40806992337,"tts":1040149}, + ]) + ).toMatchSnapshot(); + }); +}); diff --git a/src/util/preprocessDataV2.js b/src/util/preprocessDataV2.js new file mode 100644 index 0000000000000..a7dba5a64d640 --- /dev/null +++ b/src/util/preprocessDataV2.js @@ -0,0 +1,405 @@ +// @flow + +import type { TimelineEvent } from '../speedscope/import/chrome'; +import type { + Milliseconds, + BatchUID, + ReactEventV2, + ReactLane, + ReactMeasureType, + ReactProfilerDataV2, +} from '../types'; + +import { REACT_TOTAL_NUM_LANES } from '../constants'; + +type MeasureStackElement = {| + type: ReactMeasureType, + depth: number, + index: number, + startTime: Milliseconds, + stopTime?: Milliseconds, +|}; + +type ProcessorState = {| + nextRenderShouldGenerateNewBatchID: boolean, + batchUID: BatchUID, + uidCounter: BatchUID, + measureStack: MeasureStackElement[], +|}; + +/** + * Create an array containing the numbers 0 through `n`. + */ +const range = (n: number): number[] => Array.from(Array(n).keys()); + +// Exported for tests +export function getLanesFromTransportDecimalBitmask( + laneBitmaskString: string +): ReactLane[] { + const laneBitmask = parseInt(laneBitmaskString); + + // As negative numbers are stored in two's complement format, our bitmask + // checks will be thrown off by them. + if (laneBitmask < 0) { + return []; + } + + let lanes = []; + let powersOfTwo = 0; + while (powersOfTwo <= REACT_TOTAL_NUM_LANES) { + if ((1 << powersOfTwo) & laneBitmask) { + lanes.push(powersOfTwo); + } + powersOfTwo++; + } + return lanes; +} + +function getLastType(stack: $PropertyType) { + if (stack.length > 0) { + const { type } = stack[stack.length - 1]; + return type; + } + return null; +} + +function getDepth(stack: $PropertyType) { + if (stack.length > 0) { + const { depth, type } = stack[stack.length - 1]; + return type === 'render-idle' ? depth : depth + 1; + } + return 0; +} + +function markWorkStarted( + type: ReactMeasureType, + startTime: Milliseconds, + lanes: ReactLane[], + currentProfilerData: ReactProfilerDataV2, + state: ProcessorState +) { + const { batchUID, measureStack } = state; + const index = currentProfilerData.measures.length; + const depth = getDepth(measureStack); + + state.measureStack.push({ depth, index, startTime, type }); + + currentProfilerData.measures.push({ + type, + batchUID, + depth, + lanes, + timestamp: startTime, + duration: 0, + }); +} + +function markWorkCompleted( + type: ReactMeasureType, + stopTime: Milliseconds, + currentProfilerData: ReactProfilerDataV2, + stack: $PropertyType +) { + if (stack.length === 0) { + console.error( + `Unexpected type "${type}" completed at ${stopTime}ms while stack is empty.` + ); + // Ignore work "completion" user timing mark that doesn't complete anything + return; + } + + const last = stack[stack.length - 1]; + if (last.type !== type) { + console.error( + `Unexpected type "${type}" completed at ${stopTime}ms before "${last.type}" completed.` + ); + } + + const { index, startTime } = stack.pop(); + const measure = currentProfilerData.measures[index]; + if (!measure) { + console.error(`Could not find matching measure for type "${type}".`); + } + + // $FlowFixMe This property should not be writable outside of this function. + measure.duration = stopTime - startTime; +} + +function throwIfIncomplete( + type: ReactMeasureType, + stack: $PropertyType +) { + const lastIndex = stack.length - 1; + if (lastIndex >= 0) { + const last = stack[lastIndex]; + if (last.stopTime === undefined && last.type === type) { + throw new Error( + `Unexpected type "${type}" started before "${last.type}" completed.` + ); + } + } +} + +function processTimelineEvent( + event: TimelineEvent, + /** Finalized profiler data up to `event`. May be mutated. */ + currentProfilerData: ReactProfilerDataV2, + /** Intermediate processor state. May be mutated. */ + state: ProcessorState +) { + const { cat, name, ts } = event; + if (cat !== 'blink.user_timing' || !name.startsWith('--')) { + return; + } + + const startTime = (ts - currentProfilerData.startTime) / 1000; + + // React Events - schedule + if (name.startsWith('--schedule-render-')) { + const [ + componentName, + laneBitmaskString, + ...splitComponentStack + ] = name.substr(18).split('-'); + currentProfilerData.events.push({ + type: 'schedule-render', + lanes: getLanesFromTransportDecimalBitmask(laneBitmaskString), + componentName, + componentStack: splitComponentStack.join('-'), + timestamp: startTime, + }); + } else if (name.startsWith('--schedule-forced-update-')) { + const [ + componentName, + laneBitmaskString, + ...splitComponentStack + ] = name.substr(25).split('-'); + const isCascading = !!state.measureStack.find( + ({ type }) => type === 'commit' + ); + currentProfilerData.events.push({ + type: 'schedule-force-update', + lanes: getLanesFromTransportDecimalBitmask(laneBitmaskString), + componentName, + componentStack: splitComponentStack.join('-'), + timestamp: startTime, + isCascading, + }); + } else if (name.startsWith('--schedule-state-update-')) { + const [ + componentName, + laneBitmaskString, + ...splitComponentStack + ] = name.substr(24).split('-'); + const isCascading = !!state.measureStack.find( + ({ type }) => type === 'commit' + ); + currentProfilerData.events.push({ + type: 'schedule-state-update', + lanes: getLanesFromTransportDecimalBitmask(laneBitmaskString), + componentName, + componentStack: splitComponentStack.join('-'), + timestamp: startTime, + isCascading, + }); + } + + // React Events - suspense + else if (name.startsWith('--suspense-suspend-')) { + const [componentName, id, ...splitComponentStack] = name + .substr(19) + .split('-'); + currentProfilerData.events.push({ + type: 'suspense-suspend', + id, + componentName, + componentStack: splitComponentStack.join('-'), + timestamp: startTime, + }); + } else if (name.startsWith('--suspense-resolved-')) { + const [componentName, id, ...splitComponentStack] = name + .substr(20) + .split('-'); + currentProfilerData.events.push({ + type: 'suspense-resolved', + id, + componentName, + componentStack: splitComponentStack.join('-'), + timestamp: startTime, + }); + } else if (name.startsWith('--suspense-rejected-')) { + const [componentName, id, ...splitComponentStack] = name + .substr(20) + .split('-'); + currentProfilerData.events.push({ + type: 'suspense-rejected', + id, + componentName, + componentStack: splitComponentStack.join('-'), + timestamp: startTime, + }); + } + + // React Measures - render + else if (name.startsWith('--render-start-')) { + if (state.nextRenderShouldGenerateNewBatchID) { + state.nextRenderShouldGenerateNewBatchID = false; + state.batchUID = ((state.uidCounter++: any): BatchUID); + } + const laneBitmaskString = name.substr(15); + const lanes = getLanesFromTransportDecimalBitmask(laneBitmaskString); + throwIfIncomplete('render', state.measureStack); + if (getLastType(state.measureStack) !== 'render-idle') { + markWorkStarted( + 'render-idle', + startTime, + lanes, + currentProfilerData, + state + ); + } + markWorkStarted('render', startTime, lanes, currentProfilerData, state); + } else if ( + name.startsWith('--render-stop') || + name.startsWith('--render-yield') + ) { + markWorkCompleted( + 'render', + startTime, + currentProfilerData, + state.measureStack + ); + } else if (name.startsWith('--render-cancel')) { + state.nextRenderShouldGenerateNewBatchID = true; + markWorkCompleted( + 'render', + startTime, + currentProfilerData, + state.measureStack + ); + markWorkCompleted( + 'render-idle', + startTime, + currentProfilerData, + state.measureStack + ); + } + + // React Measures - commits + else if (name.startsWith('--commit-start-')) { + state.nextRenderShouldGenerateNewBatchID = true; + const laneBitmaskString = name.substr(15); + const lanes = getLanesFromTransportDecimalBitmask(laneBitmaskString); + markWorkStarted('commit', startTime, lanes, currentProfilerData, state); + } else if (name.startsWith('--commit-stop')) { + markWorkCompleted( + 'commit', + startTime, + currentProfilerData, + state.measureStack + ); + markWorkCompleted( + 'render-idle', + startTime, + currentProfilerData, + state.measureStack + ); + } + + // React Measures - layout effects + else if (name.startsWith('--layout-effects-start-')) { + const laneBitmaskString = name.substr(23); + const lanes = getLanesFromTransportDecimalBitmask(laneBitmaskString); + markWorkStarted( + 'layout-effects', + startTime, + lanes, + currentProfilerData, + state + ); + } else if (name.startsWith('--layout-effects-stop')) { + markWorkCompleted( + 'layout-effects', + startTime, + currentProfilerData, + state.measureStack + ); + } + + // React Measures - passive effects + else if (name.startsWith('--passive-effects-start-')) { + const laneBitmaskString = name.substr(24); + const lanes = getLanesFromTransportDecimalBitmask(laneBitmaskString); + markWorkStarted( + 'passive-effects', + startTime, + lanes, + currentProfilerData, + state + ); + } else if (name.startsWith('--passive-effects-stop')) { + markWorkCompleted( + 'passive-effects', + startTime, + currentProfilerData, + state.measureStack + ); + } + + // Unrecognized event + else { + throw new Error( + `Unrecognized event ${name}! This is likely a bug in this profiler tool.` + ); + } +} + +export default function preprocessData( + timeline: TimelineEvent[] +): ReactProfilerDataV2 { + const profilerData = { + startTime: 0, + duration: 0, + events: [], + measures: [], + }; + + if (timeline.length === 0) { + return profilerData; + } + + profilerData.startTime = timeline[0].ts; // TODO: Confirm with trace events doc if this is legit -- the events may not have to be ordered + + const state: ProcessorState = { + batchUID: 0, + uidCounter: 0, + nextRenderShouldGenerateNewBatchID: true, + measureStack: [], + }; + + for (const event of timeline) { + processTimelineEvent(event, profilerData, state); + } + + // Validate that all events and measures are complete + const { measureStack } = state; + if (measureStack.length > 0) { + console.error(`Incomplete events or measures`, measureStack); + } + + // Compute profilerData.duration + const { events, measures } = profilerData; + if (events.length > 0) { + const { timestamp } = events[events.length - 1]; + profilerData.duration = Math.max(profilerData.duration, timestamp); + } + if (measures.length > 0) { + const { duration, timestamp } = measures[measures.length - 1]; + profilerData.duration = Math.max( + profilerData.duration, + timestamp + duration + ); + } + + return profilerData; +} From b691699eb6fb2a24609cbb5543430c32e20a8989 Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Mon, 29 Jun 2020 14:27:40 +0800 Subject: [PATCH 022/116] Add GitHub Actions workflow (#24) * Add GitHub Actions workflow Adds CI workflow to run `yarn lint`, `yarn test`, and `yarn build`. `yarn flow` excluded for now as we still have many typecheck failures. Based on: - Default Node.js workflow - https://github.com/actions/cache/blob/master/examples.md#node---yarn * Prettify node.js.yml * Configure test script to pass with no tests Tests are currently failing as there are no tests in the codebase. This commit adds `--passWithNoTests` to make Jest not error. This commit should be reverted once there are tests in our codebase. * Revert "Configure test script to pass with no tests" This reverts commit bd57b9ea82328fb3765b91b7847eb99f51b7aae4. * Fix lint in new files on master --- .github/workflows/node.js.yml | 48 ++++++++++++ src/util/__tests__/preprocessData-test.js | 43 +++++----- src/util/preprocessDataV2.js | 96 +++++++++++------------ 3 files changed, 115 insertions(+), 72 deletions(-) create mode 100644 .github/workflows/node.js.yml diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml new file mode 100644 index 0000000000000..c7af1ec4a7e7f --- /dev/null +++ b/.github/workflows/node.js.yml @@ -0,0 +1,48 @@ +# This workflow will do a clean install of node dependencies, build the source +# code and run tests across different versions of node. +# +# For more information see: +# https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions + +name: Node.js CI + +on: + push: + branches: [master] + pull_request: + branches: [master] + +jobs: + build: + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [12.x, 14.x] + + steps: + - uses: actions/checkout@v2 + + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + + - name: Get yarn cache directory path + id: yarn-cache-dir-path + run: echo "::set-output name=dir::$(yarn cache dir)" + + - uses: actions/cache@v2 + id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`) + with: + path: ${{ steps.yarn-cache-dir-path.outputs.dir }} + key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} + restore-keys: | + ${{ runner.os }}-yarn- + + - name: Install dependencies + run: yarn --frozen-lockfile --non-interactive + + - run: yarn lint + - run: yarn test + - run: yarn build diff --git a/src/util/__tests__/preprocessData-test.js b/src/util/__tests__/preprocessData-test.js index b66e8a80165a9..f84a540eee7b5 100644 --- a/src/util/__tests__/preprocessData-test.js +++ b/src/util/__tests__/preprocessData-test.js @@ -3,7 +3,11 @@ import preprocessData, { getLanesFromTransportDecimalBitmask, } from '../preprocessDataV2'; -import { REACT_TOTAL_NUM_LANES } from '../../constants'; +import {REACT_TOTAL_NUM_LANES} from '../../constants'; + +// Disable quotes rule in the whole file as we paste raw JSON as test inputs and +// Prettier will already format the remaining quotes. +/* eslint-disable quotes */ describe(getLanesFromTransportDecimalBitmask, () => { it('should return array of lane numbers from bitmask string', () => { @@ -18,10 +22,10 @@ describe(getLanesFromTransportDecimalBitmask, () => { 10, ]); // 2 + 16 + 64 + 128 + 1024 expect( - getLanesFromTransportDecimalBitmask('1073741824') // 0b1000000000000000000000000000000 + getLanesFromTransportDecimalBitmask('1073741824'), // 0b1000000000000000000000000000000 ).toEqual([30]); expect( - getLanesFromTransportDecimalBitmask('2147483647') // 0b1111111111111111111111111111111 + getLanesFromTransportDecimalBitmask('2147483647'), // 0b1111111111111111111111111111111 ).toEqual(Array.from(Array(31).keys())); }); @@ -39,15 +43,14 @@ describe(getLanesFromTransportDecimalBitmask, () => { expect( getLanesFromTransportDecimalBitmask( - '4294967297' // 2^32 + 1 - ) + '4294967297', // 2^32 + 1 + ), ).toEqual([0]); }); }); describe(preprocessData, () => { it('should return empty data given an empty timeline', () => { - const input = []; expect(preprocessData([])).toEqual({ startTime: 0, duration: 0, @@ -57,17 +60,17 @@ describe(preprocessData, () => { }); it('should return empty data given a timeline with no React scheduling profiling marks', () => { - // prettier-ignore - const input = [ - {"pid":57632,"tid":38659,"ts":874860756135,"ph":"X","cat":"disabled-by-default-devtools.timeline","name":"RunTask","dur":18,"tdur":19,"tts":8700284918,"args":{}}, - {"pid":57632,"tid":38659,"ts":874860756158,"ph":"X","cat":"disabled-by-default-devtools.timeline","name":"RunTask","dur":30,"tdur":30,"tts":8700284941,"args":{}}, - {"pid":57632,"tid":38659,"ts":874860756192,"ph":"X","cat":"disabled-by-default-devtools.timeline","name":"RunTask","dur":21,"tdur":20,"tts":8700284976,"args":{}}, - {"pid":57632,"tid":38659,"ts":874860756216,"ph":"X","cat":"disabled-by-default-devtools.timeline","name":"RunTask","dur":6,"tdur":5,"tts":8700285000,"args":{}}, - {"pid":57632,"tid":38659,"ts":874860756224,"ph":"X","cat":"disabled-by-default-devtools.timeline","name":"RunTask","dur":7,"tdur":6,"tts":8700285008,"args":{}}, - {"pid":57632,"tid":38659,"ts":874860756233,"ph":"X","cat":"disabled-by-default-devtools.timeline","name":"RunTask","dur":5,"tdur":4,"tts":8700285017,"args":{}}, - ] - - expect(preprocessData(input)).toEqual({ + expect( + // prettier-ignore + preprocessData([ + {"pid":57632,"tid":38659,"ts":874860756135,"ph":"X","cat":"disabled-by-default-devtools.timeline","name":"RunTask","dur":18,"tdur":19,"tts":8700284918,"args":{}}, + {"pid":57632,"tid":38659,"ts":874860756158,"ph":"X","cat":"disabled-by-default-devtools.timeline","name":"RunTask","dur":30,"tdur":30,"tts":8700284941,"args":{}}, + {"pid":57632,"tid":38659,"ts":874860756192,"ph":"X","cat":"disabled-by-default-devtools.timeline","name":"RunTask","dur":21,"tdur":20,"tts":8700284976,"args":{}}, + {"pid":57632,"tid":38659,"ts":874860756216,"ph":"X","cat":"disabled-by-default-devtools.timeline","name":"RunTask","dur":6,"tdur":5,"tts":8700285000,"args":{}}, + {"pid":57632,"tid":38659,"ts":874860756224,"ph":"X","cat":"disabled-by-default-devtools.timeline","name":"RunTask","dur":7,"tdur":6,"tts":8700285008,"args":{}}, + {"pid":57632,"tid":38659,"ts":874860756233,"ph":"X","cat":"disabled-by-default-devtools.timeline","name":"RunTask","dur":5,"tdur":4,"tts":8700285017,"args":{}}, + ]), + ).toEqual({ startTime: 874860756135, duration: 0, events: [], @@ -80,7 +83,7 @@ describe(preprocessData, () => { preprocessData([ // prettier-ignore {"args":{"data":{"navigationId":"E082C30FBDA3ACEE0E7B5FD75F8B7F0D"}},"cat":"blink.user_timing","name":"--there-are-four-lights","ph":"R","pid":17232,"tid":13628,"ts":264686513020,"tts":4082554}, - ]) + ]), ).toThrow(); }); @@ -292,7 +295,7 @@ describe(preprocessData, () => { {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--layout-effects-start-16384","ph":"R","pid":9312,"tid":10252,"ts":8996364618,"tts":2273869}, {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--layout-effects-stop","ph":"R","pid":9312,"tid":10252,"ts":8996364645,"tts":2273895}, {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--commit-stop","ph":"R","pid":9312,"tid":10252,"ts":8996365391,"tts":2274547}, - ]) + ]), ).toMatchSnapshot(); }); @@ -307,7 +310,7 @@ describe(preprocessData, () => { {"args":{"data":{"navigationId":"1065756F5FDAD64BE45CA86B0BBC1F8B"}},"cat":"blink.user_timing","name":"--layout-effects-start-16","ph":"R","pid":1852,"tid":12484,"ts":40806992201,"tts":1040023}, {"args":{"data":{"navigationId":"1065756F5FDAD64BE45CA86B0BBC1F8B"}},"cat":"blink.user_timing","name":"--layout-effects-stop","ph":"R","pid":1852,"tid":12484,"ts":40806992219,"tts":1040041}, {"args":{"data":{"navigationId":"1065756F5FDAD64BE45CA86B0BBC1F8B"}},"cat":"blink.user_timing","name":"--commit-stop","ph":"R","pid":1852,"tid":12484,"ts":40806992337,"tts":1040149}, - ]) + ]), ).toMatchSnapshot(); }); }); diff --git a/src/util/preprocessDataV2.js b/src/util/preprocessDataV2.js index a7dba5a64d640..d73b3a524a383 100644 --- a/src/util/preprocessDataV2.js +++ b/src/util/preprocessDataV2.js @@ -1,16 +1,15 @@ // @flow -import type { TimelineEvent } from '../speedscope/import/chrome'; +import type {TimelineEvent} from '../speedscope/import/chrome'; import type { Milliseconds, BatchUID, - ReactEventV2, ReactLane, ReactMeasureType, ReactProfilerDataV2, } from '../types'; -import { REACT_TOTAL_NUM_LANES } from '../constants'; +import {REACT_TOTAL_NUM_LANES} from '../constants'; type MeasureStackElement = {| type: ReactMeasureType, @@ -27,16 +26,11 @@ type ProcessorState = {| measureStack: MeasureStackElement[], |}; -/** - * Create an array containing the numbers 0 through `n`. - */ -const range = (n: number): number[] => Array.from(Array(n).keys()); - // Exported for tests export function getLanesFromTransportDecimalBitmask( - laneBitmaskString: string + laneBitmaskString: string, ): ReactLane[] { - const laneBitmask = parseInt(laneBitmaskString); + const laneBitmask = parseInt(laneBitmaskString, 10); // As negative numbers are stored in two's complement format, our bitmask // checks will be thrown off by them. @@ -44,7 +38,7 @@ export function getLanesFromTransportDecimalBitmask( return []; } - let lanes = []; + const lanes = []; let powersOfTwo = 0; while (powersOfTwo <= REACT_TOTAL_NUM_LANES) { if ((1 << powersOfTwo) & laneBitmask) { @@ -57,7 +51,7 @@ export function getLanesFromTransportDecimalBitmask( function getLastType(stack: $PropertyType) { if (stack.length > 0) { - const { type } = stack[stack.length - 1]; + const {type} = stack[stack.length - 1]; return type; } return null; @@ -65,7 +59,7 @@ function getLastType(stack: $PropertyType) { function getDepth(stack: $PropertyType) { if (stack.length > 0) { - const { depth, type } = stack[stack.length - 1]; + const {depth, type} = stack[stack.length - 1]; return type === 'render-idle' ? depth : depth + 1; } return 0; @@ -76,13 +70,13 @@ function markWorkStarted( startTime: Milliseconds, lanes: ReactLane[], currentProfilerData: ReactProfilerDataV2, - state: ProcessorState + state: ProcessorState, ) { - const { batchUID, measureStack } = state; + const {batchUID, measureStack} = state; const index = currentProfilerData.measures.length; const depth = getDepth(measureStack); - state.measureStack.push({ depth, index, startTime, type }); + state.measureStack.push({depth, index, startTime, type}); currentProfilerData.measures.push({ type, @@ -98,11 +92,11 @@ function markWorkCompleted( type: ReactMeasureType, stopTime: Milliseconds, currentProfilerData: ReactProfilerDataV2, - stack: $PropertyType + stack: $PropertyType, ) { if (stack.length === 0) { console.error( - `Unexpected type "${type}" completed at ${stopTime}ms while stack is empty.` + `Unexpected type "${type}" completed at ${stopTime}ms while stack is empty.`, ); // Ignore work "completion" user timing mark that doesn't complete anything return; @@ -111,11 +105,11 @@ function markWorkCompleted( const last = stack[stack.length - 1]; if (last.type !== type) { console.error( - `Unexpected type "${type}" completed at ${stopTime}ms before "${last.type}" completed.` + `Unexpected type "${type}" completed at ${stopTime}ms before "${last.type}" completed.`, ); } - const { index, startTime } = stack.pop(); + const {index, startTime} = stack.pop(); const measure = currentProfilerData.measures[index]; if (!measure) { console.error(`Could not find matching measure for type "${type}".`); @@ -127,14 +121,14 @@ function markWorkCompleted( function throwIfIncomplete( type: ReactMeasureType, - stack: $PropertyType + stack: $PropertyType, ) { const lastIndex = stack.length - 1; if (lastIndex >= 0) { const last = stack[lastIndex]; if (last.stopTime === undefined && last.type === type) { throw new Error( - `Unexpected type "${type}" started before "${last.type}" completed.` + `Unexpected type "${type}" started before "${last.type}" completed.`, ); } } @@ -145,9 +139,9 @@ function processTimelineEvent( /** Finalized profiler data up to `event`. May be mutated. */ currentProfilerData: ReactProfilerDataV2, /** Intermediate processor state. May be mutated. */ - state: ProcessorState + state: ProcessorState, ) { - const { cat, name, ts } = event; + const {cat, name, ts} = event; if (cat !== 'blink.user_timing' || !name.startsWith('--')) { return; } @@ -175,7 +169,7 @@ function processTimelineEvent( ...splitComponentStack ] = name.substr(25).split('-'); const isCascading = !!state.measureStack.find( - ({ type }) => type === 'commit' + ({type}) => type === 'commit', ); currentProfilerData.events.push({ type: 'schedule-force-update', @@ -192,7 +186,7 @@ function processTimelineEvent( ...splitComponentStack ] = name.substr(24).split('-'); const isCascading = !!state.measureStack.find( - ({ type }) => type === 'commit' + ({type}) => type === 'commit', ); currentProfilerData.events.push({ type: 'schedule-state-update', @@ -202,7 +196,7 @@ function processTimelineEvent( timestamp: startTime, isCascading, }); - } + } // eslint-disable-line brace-style // React Events - suspense else if (name.startsWith('--suspense-suspend-')) { @@ -238,7 +232,7 @@ function processTimelineEvent( componentStack: splitComponentStack.join('-'), timestamp: startTime, }); - } + } // eslint-disable-line brace-style // React Measures - render else if (name.startsWith('--render-start-')) { @@ -255,7 +249,7 @@ function processTimelineEvent( startTime, lanes, currentProfilerData, - state + state, ); } markWorkStarted('render', startTime, lanes, currentProfilerData, state); @@ -267,7 +261,7 @@ function processTimelineEvent( 'render', startTime, currentProfilerData, - state.measureStack + state.measureStack, ); } else if (name.startsWith('--render-cancel')) { state.nextRenderShouldGenerateNewBatchID = true; @@ -275,15 +269,15 @@ function processTimelineEvent( 'render', startTime, currentProfilerData, - state.measureStack + state.measureStack, ); markWorkCompleted( 'render-idle', startTime, currentProfilerData, - state.measureStack + state.measureStack, ); - } + } // eslint-disable-line brace-style // React Measures - commits else if (name.startsWith('--commit-start-')) { @@ -296,15 +290,15 @@ function processTimelineEvent( 'commit', startTime, currentProfilerData, - state.measureStack + state.measureStack, ); markWorkCompleted( 'render-idle', startTime, currentProfilerData, - state.measureStack + state.measureStack, ); - } + } // eslint-disable-line brace-style // React Measures - layout effects else if (name.startsWith('--layout-effects-start-')) { @@ -315,16 +309,16 @@ function processTimelineEvent( startTime, lanes, currentProfilerData, - state + state, ); } else if (name.startsWith('--layout-effects-stop')) { markWorkCompleted( 'layout-effects', startTime, currentProfilerData, - state.measureStack + state.measureStack, ); - } + } // eslint-disable-line brace-style // React Measures - passive effects else if (name.startsWith('--passive-effects-start-')) { @@ -335,27 +329,27 @@ function processTimelineEvent( startTime, lanes, currentProfilerData, - state + state, ); } else if (name.startsWith('--passive-effects-stop')) { markWorkCompleted( 'passive-effects', startTime, currentProfilerData, - state.measureStack + state.measureStack, ); - } + } // eslint-disable-line brace-style // Unrecognized event else { throw new Error( - `Unrecognized event ${name}! This is likely a bug in this profiler tool.` + `Unrecognized event ${name}! This is likely a bug in this profiler tool.`, ); } } export default function preprocessData( - timeline: TimelineEvent[] + timeline: TimelineEvent[], ): ReactProfilerDataV2 { const profilerData = { startTime: 0, @@ -377,27 +371,25 @@ export default function preprocessData( measureStack: [], }; - for (const event of timeline) { - processTimelineEvent(event, profilerData, state); - } + timeline.forEach(event => processTimelineEvent(event, profilerData, state)); // Validate that all events and measures are complete - const { measureStack } = state; + const {measureStack} = state; if (measureStack.length > 0) { console.error(`Incomplete events or measures`, measureStack); } // Compute profilerData.duration - const { events, measures } = profilerData; + const {events, measures} = profilerData; if (events.length > 0) { - const { timestamp } = events[events.length - 1]; + const {timestamp} = events[events.length - 1]; profilerData.duration = Math.max(profilerData.duration, timestamp); } if (measures.length > 0) { - const { duration, timestamp } = measures[measures.length - 1]; + const {duration, timestamp} = measures[measures.length - 1]; profilerData.duration = Math.max( profilerData.duration, - timestamp + duration + timestamp + duration, ); } From 3d8c83e7717b18fc8b29efc87b8bfc9d6ad95b3f Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Mon, 29 Jun 2020 19:31:11 +0800 Subject: [PATCH 023/116] Break App.js into CanvasPage and ImportPage (#25) * Unexport unnecessary exported vars in src/canvas * Remove unused App.css classes * Extract CanvasPage from App.js and clean up now-non-nullable types * Wrap App in React.StrictMode * Extract automatic ImportPage from App.js * Wrap App updates in batchedUpdates --- src/App.css | 17 --- src/App.js | 294 +++++-------------------------------- src/CanvasPage.css | 7 + src/CanvasPage.js | 229 +++++++++++++++++++++++++++++ src/EventTooltip.js | 8 +- src/ImportPage.js | 45 ++++++ src/canvas/canvasUtils.js | 212 +++++++++++++------------- src/canvas/renderCanvas.js | 2 +- src/index.js | 9 +- 9 files changed, 429 insertions(+), 394 deletions(-) delete mode 100644 src/App.css create mode 100644 src/CanvasPage.css create mode 100644 src/CanvasPage.js create mode 100644 src/ImportPage.js diff --git a/src/App.css b/src/App.css deleted file mode 100644 index b5d535517bc90..0000000000000 --- a/src/App.css +++ /dev/null @@ -1,17 +0,0 @@ -.App { - position: absolute; - top: 0.5rem; - bottom: 0.5rem; - left: 0.5rem; - right: 0.5rem; -} - -.Canvas { -} - -.HighlightContainer { - pointer-events: none; - position: absolute; - top: 0; - overflow: hidden; -} diff --git a/src/App.js b/src/App.js index a01446a2d5d21..52f0470c08340 100644 --- a/src/App.js +++ b/src/App.js @@ -1,274 +1,48 @@ // @flow -import type {TimelineEvent} from './speedscope/import/chrome'; -import type {PanAndZoomState} from './util/usePanAndZoom'; +import type {FlamechartData, ReactProfilerData} from './types'; -import {copy} from 'clipboard-js'; -import React, { - Fragment, - useEffect, - useLayoutEffect, - useRef, - useState, -} from 'react'; +import React, {useState, useCallback} from 'react'; import {unstable_batchedUpdates} from 'react-dom'; -import usePanAndZoom from './util/usePanAndZoom'; -import {getHoveredEvent, getPriorityHeight} from './canvas/canvasUtils'; -import {renderCanvas} from './canvas/renderCanvas'; +import {getPriorityHeight} from './canvas/canvasUtils'; +import {REACT_PRIORITIES} from './canvas/constants'; +import ImportPage from './ImportPage'; +import CanvasPage from './CanvasPage'; -import prettyMilliseconds from 'pretty-ms'; -import {getBatchRange} from './util/getBatchRange'; -import EventTooltip from './EventTooltip'; -import preprocessData from './util/preprocessData'; -import preprocessFlamechart from './util/preprocessFlamechart'; -import styles from './App.css'; -import AutoSizer from 'react-virtualized-auto-sizer'; -import { - COLORS, - REACT_PRIORITIES, - FLAMECHART_FRAME_HEIGHT, - LABEL_FIXED_WIDTH, - HEADER_HEIGHT_FIXED, -} from './canvas/constants'; - -import {ContextMenu, ContextMenuItem, useContextMenu} from './context'; - -// TODO: Add import button but keep a static path until canvas layout is ready -import JSON_PATH from 'url:../static/small-devtools.json'; - -const CONTEXT_MENU_ID = 'canvas'; - -import type { - FlamechartData, - ReactHoverContextInfo, - ReactMeasure, - ReactProfilerData, -} from './types'; - -type ContextMenuContextData = {| - data: ReactProfilerData | null, - flamechart: FlamechartData | null, - hoveredEvent: ReactHoverContextInfo | null, - state: PanAndZoomState, -|}; - -function App() { - const [data, setData] = useState(null); +export default function App() { + const [profilerData, setProfilerData] = useState( + null, + ); const [flamechart, setFlamechart] = useState(null); const [schedulerCanvasHeight, setSchedulerCanvasHeight] = useState(0); - useEffect(() => { - fetch(JSON_PATH) - .then(res => res.json()) - .then((events: TimelineEvent[]) => { - // Filter null entries and sort by timestamp. - // I would not expect to have to do either of this, - // but some of the data being passed in requires it. - events = events.filter(Boolean).sort((a, b) => (a.ts > b.ts ? 1 : -1)); - - if (events.length > 0) { - unstable_batchedUpdates(() => { - const processedData = preprocessData(events); - setData(processedData); - - setFlamechart(preprocessFlamechart(events)); - - let height = 0; - - REACT_PRIORITIES.forEach(priority => { - height += getPriorityHeight(processedData, priority); - }); - - setSchedulerCanvasHeight(height); - }); - } + const handleDataImported = useCallback( + ( + importedProfilerData: ReactProfilerData, + importedFlamechart: FlamechartData, + ) => { + unstable_batchedUpdates(() => { + setSchedulerCanvasHeight( + REACT_PRIORITIES.reduce((height, priority) => { + return height + getPriorityHeight(importedProfilerData, priority); + }, 0), + ); + setProfilerData(importedProfilerData); + setFlamechart(importedFlamechart); }); - }, []); - - return ( -
- - {({height, width}: {height: number, width: number}) => ( - - )} - -
- ); -} - -const copySummary = (data: ReactProfilerData | null, measure: ReactMeasure) => { - const {batchUID, duration, priority, timestamp, type} = measure; - - const [startTime, stopTime] = getBatchRange(batchUID, priority, data); - - copy( - JSON.stringify({ - type, - timestamp: prettyMilliseconds(timestamp), - duration: prettyMilliseconds(duration), - batchDuration: prettyMilliseconds(stopTime - startTime), - }), - ); -}; - -const zoomToBatch = ( - data: ReactProfilerData | null, - measure: ReactMeasure, - state: PanAndZoomState, -) => { - const {zoomTo} = state; - if (!data || !zoomTo) { - return; - } - const {batchUID, priority} = measure; - const [startTime, stopTime] = getBatchRange(batchUID, priority, data); - zoomTo(startTime, stopTime); -}; - -type AutoSizedCanvasProps = {| - data: ReactProfilerData | null, - flamechart: FlamechartData | null, - height: number, - schedulerCanvasHeight: number, - width: number, -|}; - -function AutoSizedCanvas({ - data, - flamechart, - height, - schedulerCanvasHeight, - width, -}: AutoSizedCanvasProps) { - const canvasRef = useRef(null); - - const state = usePanAndZoom({ - canvasRef, - canvasHeight: height, - canvasWidth: width, - fixedColumnWidth: LABEL_FIXED_WIDTH, - fixedHeaderHeight: HEADER_HEIGHT_FIXED, - unscaledContentWidth: data != null ? data.duration : 0, - unscaledContentHeight: - data != null - ? schedulerCanvasHeight + - flamechart.layers.length * FLAMECHART_FRAME_HEIGHT - : 0, - }); - - const hoveredEvent = getHoveredEvent( - schedulerCanvasHeight, - data, - flamechart, - state, - ); - const [isContextMenuShown, setIsContextMenuShown] = useState(false); - - useContextMenu({ - data: { - data, - flamechart, - hoveredEvent, - state, }, - id: CONTEXT_MENU_ID, - onChange: setIsContextMenuShown, - ref: canvasRef, - }); - - useLayoutEffect(() => { - if (data !== null) { - renderCanvas( - data, - flamechart, - canvasRef.current, - width, - height, - schedulerCanvasHeight, - state, - hoveredEvent, - ); - } - }); + ); - return ( - - - - {(contextData: ContextMenuContextData) => { - if (contextData.hoveredEvent == null) { - return null; - } - const {event, flamechartNode, measure} = contextData.hoveredEvent; - return ( - - {event !== null && ( - copy(event.componentName)} - title="Copy component name"> - Copy component name - - )} - {event !== null && ( - copy(event.componentStack)} - title="Copy component stack"> - Copy component stack - - )} - {measure !== null && ( - zoomToBatch(contextData.data, measure, state)} - title="Zoom to batch"> - Zoom to batch - - )} - {measure !== null && ( - copySummary(contextData.data, measure)} - title="Copy summary"> - Copy summary - - )} - {flamechartNode !== null && ( - copy(flamechartNode.node.frame.file)} - title="Copy file path"> - Copy file path - - )} - {flamechartNode !== null && ( - - copy( - `line ${flamechartNode.node.frame.line}, column ${flamechartNode.node.frame.col}`, - ) - } - title="Copy location"> - Copy location - - )} - - ); - }} - - {!isContextMenuShown && ( - - )} - - ); + ); + } else { + return ; + } } - -export default App; diff --git a/src/CanvasPage.css b/src/CanvasPage.css new file mode 100644 index 0000000000000..e5d238a0d9d2c --- /dev/null +++ b/src/CanvasPage.css @@ -0,0 +1,7 @@ +.CanvasPage { + position: absolute; + top: 0.5rem; + bottom: 0.5rem; + left: 0.5rem; + right: 0.5rem; +} diff --git a/src/CanvasPage.js b/src/CanvasPage.js new file mode 100644 index 0000000000000..239933da2cfa8 --- /dev/null +++ b/src/CanvasPage.js @@ -0,0 +1,229 @@ +// @flow + +import type {PanAndZoomState} from './util/usePanAndZoom'; + +import {copy} from 'clipboard-js'; +import React, {Fragment, useLayoutEffect, useRef, useState} from 'react'; +import usePanAndZoom from './util/usePanAndZoom'; + +import {getHoveredEvent} from './canvas/canvasUtils'; +import {renderCanvas} from './canvas/renderCanvas'; + +import prettyMilliseconds from 'pretty-ms'; +import {getBatchRange} from './util/getBatchRange'; +import EventTooltip from './EventTooltip'; +import styles from './CanvasPage.css'; +import AutoSizer from 'react-virtualized-auto-sizer'; +import { + COLORS, + FLAMECHART_FRAME_HEIGHT, + LABEL_FIXED_WIDTH, + HEADER_HEIGHT_FIXED, +} from './canvas/constants'; + +import {ContextMenu, ContextMenuItem, useContextMenu} from './context'; + +const CONTEXT_MENU_ID = 'canvas'; + +import type { + FlamechartData, + ReactHoverContextInfo, + ReactMeasure, + ReactProfilerData, +} from './types'; + +type ContextMenuContextData = {| + data: ReactProfilerData, + flamechart: FlamechartData, + hoveredEvent: ReactHoverContextInfo | null, + state: PanAndZoomState, +|}; + +type Props = {| + profilerData: ReactProfilerData, + flamechart: FlamechartData, + schedulerCanvasHeight: number, +|}; + +function CanvasPage({profilerData, flamechart, schedulerCanvasHeight}: Props) { + return ( +
+ + {({height, width}: {height: number, width: number}) => ( + + )} + +
+ ); +} + +const copySummary = (data: ReactProfilerData, measure: ReactMeasure) => { + const {batchUID, duration, priority, timestamp, type} = measure; + + const [startTime, stopTime] = getBatchRange(batchUID, priority, data); + + copy( + JSON.stringify({ + type, + timestamp: prettyMilliseconds(timestamp), + duration: prettyMilliseconds(duration), + batchDuration: prettyMilliseconds(stopTime - startTime), + }), + ); +}; + +const zoomToBatch = ( + data: ReactProfilerData, + measure: ReactMeasure, + state: PanAndZoomState, +) => { + const {zoomTo} = state; + if (!zoomTo) { + return; + } + const {batchUID, priority} = measure; + const [startTime, stopTime] = getBatchRange(batchUID, priority, data); + zoomTo(startTime, stopTime); +}; + +type AutoSizedCanvasProps = {| + data: ReactProfilerData, + flamechart: FlamechartData, + height: number, + schedulerCanvasHeight: number, + width: number, +|}; + +function AutoSizedCanvas({ + data, + flamechart, + height, + schedulerCanvasHeight, + width, +}: AutoSizedCanvasProps) { + const canvasRef = useRef(null); + + const state = usePanAndZoom({ + canvasRef, + canvasHeight: height, + canvasWidth: width, + fixedColumnWidth: LABEL_FIXED_WIDTH, + fixedHeaderHeight: HEADER_HEIGHT_FIXED, + unscaledContentWidth: data.duration, + unscaledContentHeight: + schedulerCanvasHeight + + flamechart.layers.length * FLAMECHART_FRAME_HEIGHT, + }); + + const hoveredEvent = getHoveredEvent( + schedulerCanvasHeight, + data, + flamechart, + state, + ); + const [isContextMenuShown, setIsContextMenuShown] = useState(false); + + useContextMenu({ + data: { + data, + flamechart, + hoveredEvent, + state, + }, + id: CONTEXT_MENU_ID, + onChange: setIsContextMenuShown, + ref: canvasRef, + }); + + useLayoutEffect(() => { + if (data !== null) { + renderCanvas( + data, + flamechart, + canvasRef.current, + width, + height, + schedulerCanvasHeight, + state, + hoveredEvent, + ); + } + }); + + return ( + + + + {(contextData: ContextMenuContextData) => { + if (contextData.hoveredEvent == null) { + return null; + } + const {event, flamechartNode, measure} = contextData.hoveredEvent; + return ( + + {event !== null && ( + copy(event.componentName)} + title="Copy component name"> + Copy component name + + )} + {event !== null && ( + copy(event.componentStack)} + title="Copy component stack"> + Copy component stack + + )} + {measure !== null && ( + zoomToBatch(contextData.data, measure, state)} + title="Zoom to batch"> + Zoom to batch + + )} + {measure !== null && ( + copySummary(contextData.data, measure)} + title="Copy summary"> + Copy summary + + )} + {flamechartNode !== null && ( + copy(flamechartNode.node.frame.file)} + title="Copy file path"> + Copy file path + + )} + {flamechartNode !== null && ( + + copy( + `line ${flamechartNode.node.frame.line}, column ${flamechartNode.node.frame.col}`, + ) + } + title="Copy location"> + Copy location + + )} + + ); + }} + + {!isContextMenuShown && ( + + )} + + ); +} + +export default CanvasPage; diff --git a/src/EventTooltip.js b/src/EventTooltip.js index a9b5037dfd566..3c7415b4b8c22 100644 --- a/src/EventTooltip.js +++ b/src/EventTooltip.js @@ -18,7 +18,7 @@ import useSmartTooltip from './util/useSmartTooltip'; import styles from './EventTooltip.css'; type Props = {| - data: ReactProfilerData | null, + data: ReactProfilerData, hoveredEvent: ReactHoverContextInfo | null, state: PanAndZoomState, |}; @@ -118,7 +118,7 @@ const TooltipFlamechartNode = ({ flamechartNode, tooltipRef, }: { - data: ReactProfilerData | null, + data: ReactProfilerData, flamechartNode: FlamechartFrame, tooltipRef: Return, }) => { @@ -149,7 +149,7 @@ const TooltipReactEvent = ({ tooltipRef, }: { color: string, - data: ReactProfilerData | null, + data: ReactProfilerData, event: ReactEvent, tooltipRef: Return, }) => { @@ -206,7 +206,7 @@ const TooltipReactMeasure = ({ measure, tooltipRef, }: { - data: ReactProfilerData | null, + data: ReactProfilerData, measure: ReactMeasure, tooltipRef: Return, }) => { diff --git a/src/ImportPage.js b/src/ImportPage.js new file mode 100644 index 0000000000000..a7070fb3c8555 --- /dev/null +++ b/src/ImportPage.js @@ -0,0 +1,45 @@ +// @flow + +import type {TimelineEvent} from './speedscope/import/chrome'; +import type {FlamechartData, ReactProfilerData} from './types'; + +import React, {useEffect} from 'react'; + +import preprocessData from './util/preprocessData'; +import preprocessFlamechart from './util/preprocessFlamechart'; + +// TODO: Add import button but keep a static path until canvas layout is ready +import JSON_PATH from 'url:../static/small-devtools.json'; + +type Props = {| + onDataImported: ( + profilerData: ReactProfilerData, + flamechart: FlamechartData, + ) => void, +|}; + +export default function ImportPage({onDataImported}: Props) { + useEffect(() => { + fetch(JSON_PATH) + .then(res => res.json()) + .then((events: TimelineEvent[]) => { + // Filter null entries and sort by timestamp. + // I would not expect to have to do either of this, + // but some of the data being passed in requires it. + events = events.filter(Boolean).sort((a, b) => (a.ts > b.ts ? 1 : -1)); + + if (events.length > 0) { + const processedData = preprocessData(events); + const processedFlamechart = preprocessFlamechart(events); + onDataImported(processedData, processedFlamechart); + } + }); + }, []); + + return ( +
+ LOADING. TODO: Turn this into an import page. This page currently just + immediately loads a JSON file. +
+ ); +} diff --git a/src/canvas/canvasUtils.js b/src/canvas/canvasUtils.js index 5f92bd0036d29..88064f0ed693e 100644 --- a/src/canvas/canvasUtils.js +++ b/src/canvas/canvasUtils.js @@ -29,11 +29,7 @@ import { } from '../util/usePanAndZoom'; // hidpi canvas: https://www.html5rocks.com/en/tutorials/canvas/hidpi/ -export function configureRetinaCanvas( - canvas: HTMLCanvasElement, - height: number, - width: number, -): number { +function configureRetinaCanvas(canvas, height, width) { const dpr: number = window.devicePixelRatio || 1; canvas.width = width * dpr; canvas.height = height * dpr; @@ -89,7 +85,7 @@ export function getTimeTickInterval(zoomLevel: number) { return interval; } -export const cachedFlamegraphTextWidths = new Map(); +const cachedFlamegraphTextWidths = new Map(); export const trimFlamegraphText = ( context: CanvasRenderingContext2D, text: string, @@ -114,8 +110,8 @@ export const trimFlamegraphText = ( export function getHoveredEvent( schedulerCanvasHeight: number, - data: ReactProfilerData | null, - flamechart: FlamechartData | null, + data: ReactProfilerData, + flamechart: FlamechartData, state: PanAndZoomState, ): ReactHoverContextInfo | null { const {canvasMouseX, canvasMouseY, offsetY} = state; @@ -125,117 +121,113 @@ export function getHoveredEvent( } if (canvasMouseY + offsetY < schedulerCanvasHeight) { - if (data != null) { - const adjustedCanvasMouseY = canvasMouseY - HEADER_HEIGHT_FIXED + offsetY; - let priorityMinY = HEADER_HEIGHT_FIXED; - let priorityIndex = null; - let priority: ReactPriority = 'unscheduled'; - for (let index = 0; index < REACT_PRIORITIES.length; index++) { - priority = REACT_PRIORITIES[index]; - - const priorityHeight = getPriorityHeight(data, priority); - if ( - adjustedCanvasMouseY >= priorityMinY && - adjustedCanvasMouseY <= priorityMinY + priorityHeight - ) { - priorityIndex = index; - break; - } - priorityMinY += priorityHeight; + const adjustedCanvasMouseY = canvasMouseY - HEADER_HEIGHT_FIXED + offsetY; + let priorityMinY = HEADER_HEIGHT_FIXED; + let priorityIndex = null; + let priority: ReactPriority = 'unscheduled'; + for (let index = 0; index < REACT_PRIORITIES.length; index++) { + priority = REACT_PRIORITIES[index]; + + const priorityHeight = getPriorityHeight(data, priority); + if ( + adjustedCanvasMouseY >= priorityMinY && + adjustedCanvasMouseY <= priorityMinY + priorityHeight + ) { + priorityIndex = index; + break; } + priorityMinY += priorityHeight; + } - if (priorityIndex === null) { - return null; - } + if (priorityIndex === null) { + return null; + } - const baseY = priorityMinY - offsetY; - const eventMinY = baseY + REACT_GUTTER_SIZE / 2; - const eventMaxY = eventMinY + REACT_EVENT_SIZE + REACT_GUTTER_SIZE; - const measureMinY = eventMaxY; - const measureMaxY = measureMinY + REACT_WORK_SIZE + REACT_GUTTER_SIZE; - - let events = null; - let measures = null; - if (canvasMouseY >= eventMinY && canvasMouseY <= eventMaxY) { - events = data[priority].events; - } else if (canvasMouseY >= measureMinY && canvasMouseY <= measureMaxY) { - measures = data[priority].measures; - } + const baseY = priorityMinY - offsetY; + const eventMinY = baseY + REACT_GUTTER_SIZE / 2; + const eventMaxY = eventMinY + REACT_EVENT_SIZE + REACT_GUTTER_SIZE; + const measureMinY = eventMaxY; + const measureMaxY = measureMinY + REACT_WORK_SIZE + REACT_GUTTER_SIZE; + + let events = null; + let measures = null; + if (canvasMouseY >= eventMinY && canvasMouseY <= eventMaxY) { + events = data[priority].events; + } else if (canvasMouseY >= measureMinY && canvasMouseY <= measureMaxY) { + measures = data[priority].measures; + } - if (events !== null) { - for (let index = events.length - 1; index >= 0; index--) { - const event = events[index]; - const {timestamp} = event; - - const eventX = timestampToPosition(timestamp, state); - const startX = eventX - REACT_EVENT_SIZE / 2; - const stopX = eventX + REACT_EVENT_SIZE / 2; - if (canvasMouseX >= startX && canvasMouseX <= stopX) { - return { - event, - flamechartNode: null, - measure: null, - priorityIndex, - data, - }; - } + if (events !== null) { + for (let index = events.length - 1; index >= 0; index--) { + const event = events[index]; + const {timestamp} = event; + + const eventX = timestampToPosition(timestamp, state); + const startX = eventX - REACT_EVENT_SIZE / 2; + const stopX = eventX + REACT_EVENT_SIZE / 2; + if (canvasMouseX >= startX && canvasMouseX <= stopX) { + return { + event, + flamechartNode: null, + measure: null, + priorityIndex, + data, + }; } - } else if (measures !== null) { - // Because data ranges may overlap, we want to find the last intersecting item. - // This will always be the one on "top" (the one the user is hovering over). - for (let index = measures.length - 1; index >= 0; index--) { - const measure = measures[index]; - const {duration, timestamp} = measure; - - const pointerTime = positionToTimestamp(canvasMouseX, state); - - if (pointerTime >= timestamp && pointerTime <= timestamp + duration) { - return { - event: null, - flamechartNode: null, - measure, - priorityIndex, - data, - }; - } + } + } else if (measures !== null) { + // Because data ranges may overlap, we want to find the last intersecting item. + // This will always be the one on "top" (the one the user is hovering over). + for (let index = measures.length - 1; index >= 0; index--) { + const measure = measures[index]; + const {duration, timestamp} = measure; + + const pointerTime = positionToTimestamp(canvasMouseX, state); + + if (pointerTime >= timestamp && pointerTime <= timestamp + duration) { + return { + event: null, + flamechartNode: null, + measure, + priorityIndex, + data, + }; } } } } else { - if (flamechart !== null) { - const layerIndex = Math.floor( - (canvasMouseY + offsetY - HEADER_HEIGHT_FIXED - schedulerCanvasHeight) / - FLAMECHART_FRAME_HEIGHT, - ); - const layer = flamechart.layers[layerIndex]; - - if (layer != null) { - let startIndex = 0; - let stopIndex = layer.length - 1; - while (startIndex <= stopIndex) { - const currentIndex = Math.floor((startIndex + stopIndex) / 2); - const flamechartNode = layer[currentIndex]; - - const {end, start} = flamechartNode; - - const width = durationToWidth((end - start) / 1000, state); - const x = Math.floor(timestampToPosition(start / 1000, state)); - - if (x <= canvasMouseX && x + width >= canvasMouseX) { - return { - event: null, - flamechartNode, - measure: null, - priorityIndex: null, - data, - }; - } - - if (x > canvasMouseX) { - stopIndex = currentIndex - 1; - } else { - startIndex = currentIndex + 1; - } + const layerIndex = Math.floor( + (canvasMouseY + offsetY - HEADER_HEIGHT_FIXED - schedulerCanvasHeight) / + FLAMECHART_FRAME_HEIGHT, + ); + const layer = flamechart.layers[layerIndex]; + + if (layer != null) { + let startIndex = 0; + let stopIndex = layer.length - 1; + while (startIndex <= stopIndex) { + const currentIndex = Math.floor((startIndex + stopIndex) / 2); + const flamechartNode = layer[currentIndex]; + + const {end, start} = flamechartNode; + + const width = durationToWidth((end - start) / 1000, state); + const x = Math.floor(timestampToPosition(start / 1000, state)); + + if (x <= canvasMouseX && x + width >= canvasMouseX) { + return { + event: null, + flamechartNode, + measure: null, + priorityIndex: null, + data, + }; + } + + if (x > canvasMouseX) { + stopIndex = currentIndex - 1; + } else { + startIndex = currentIndex + 1; } } } diff --git a/src/canvas/renderCanvas.js b/src/canvas/renderCanvas.js index ea116126b21d9..ca9901b10f6d4 100644 --- a/src/canvas/renderCanvas.js +++ b/src/canvas/renderCanvas.js @@ -77,7 +77,7 @@ import { // '────────────────────────── // -export const renderReact = ({ +const renderReact = ({ baseY, canvasWidth, context, diff --git a/src/index.js b/src/index.js index fb86a18a32043..4eea703ec3e2c 100644 --- a/src/index.js +++ b/src/index.js @@ -1,8 +1,13 @@ -import {createElement} from 'react'; +import React from 'react'; import {render} from 'react-dom'; import App from './App'; import './index.css'; const container = document.getElementById('root'); -render(createElement(App), container); +render( + + + , + container, +); From ea2ebfa483dcef3a1b4c3055719a61331d0070bc Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Tue, 30 Jun 2020 10:29:00 +0800 Subject: [PATCH 024/116] Fix preprocessDataV2 to prevent enormous React timestamps `preprocessDataV2` previously took the `ts` value of the first timeline event, following `preprocessData`. However, this is problematic with Chrome performance data, as Chrome sticks a bunch of metadata events (i.e. `ph === 'M'`) with `ts === 0`. This caused the computed React events and measures to have enormous `timestamp` values, since they were now offset from 0 instead of being offset from the first event. This commit fixes this issue by taking the `ts` value of the first event with a non-zero and non-undefined `ts`. This fix was implemented with reference to the trace event doc: https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview 1. V2 measures now appear correctly in WIP (not pushed) canvas with V2 data. 1. CI. Tests still passing. --- src/util/preprocessDataV2.js | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/util/preprocessDataV2.js b/src/util/preprocessDataV2.js index d73b3a524a383..e9a08e770ab87 100644 --- a/src/util/preprocessDataV2.js +++ b/src/util/preprocessDataV2.js @@ -358,11 +358,22 @@ export default function preprocessData( measures: [], }; - if (timeline.length === 0) { + // TODO: Sort `timeline`. JSON Array Format trace events need not be ordered. See: + // https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview#heading=h.f2f0yd51wi15 + + const indexOfFirstEventWithTs = timeline.findIndex(event => !!event.ts); + + // Our user timing events are Complete Events (i.e. ph === 'X') and will + // always have ts. If there are no ts events, we can safely abort, knowing + // that there are no events to process. + // See: https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview#heading=h.lpfof2aylapb + if (indexOfFirstEventWithTs === -1) { return profilerData; } - profilerData.startTime = timeline[0].ts; // TODO: Confirm with trace events doc if this is legit -- the events may not have to be ordered + // `profilerData.startTime` cannot be 0 or undefined, otherwise the final + // computed React measures will have enormous `timestamp` values. + profilerData.startTime = timeline[indexOfFirstEventWithTs].ts; const state: ProcessorState = { batchUID: 0, From dfdece85dc922fb524a874741bd41b6d03c69cd9 Mon Sep 17 00:00:00 2001 From: Kartik Choudhary Date: Tue, 30 Jun 2020 20:08:19 +0530 Subject: [PATCH 025/116] Update proptypes to v2 --- src/App.js | 6 +++--- src/CanvasPage.js | 6 +++++- src/ImportPage.js | 7 +++++-- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/App.js b/src/App.js index 52f0470c08340..e9e3306e2ee95 100644 --- a/src/App.js +++ b/src/App.js @@ -1,6 +1,6 @@ // @flow -import type {FlamechartData, ReactProfilerData} from './types'; +import type {FlamechartData, ReactProfilerDataV2} from './types'; import React, {useState, useCallback} from 'react'; import {unstable_batchedUpdates} from 'react-dom'; @@ -11,7 +11,7 @@ import ImportPage from './ImportPage'; import CanvasPage from './CanvasPage'; export default function App() { - const [profilerData, setProfilerData] = useState( + const [profilerData, setProfilerData] = useState( null, ); const [flamechart, setFlamechart] = useState(null); @@ -19,7 +19,7 @@ export default function App() { const handleDataImported = useCallback( ( - importedProfilerData: ReactProfilerData, + importedProfilerData: ReactProfilerDataV2, importedFlamechart: FlamechartData, ) => { unstable_batchedUpdates(() => { diff --git a/src/CanvasPage.js b/src/CanvasPage.js index 239933da2cfa8..c37707f1e2de2 100644 --- a/src/CanvasPage.js +++ b/src/CanvasPage.js @@ -30,17 +30,19 @@ import type { ReactHoverContextInfo, ReactMeasure, ReactProfilerData, + ReactProfilerDataV2, } from './types'; type ContextMenuContextData = {| data: ReactProfilerData, + dataV2: ReactProfilerDataV2, flamechart: FlamechartData, hoveredEvent: ReactHoverContextInfo | null, state: PanAndZoomState, |}; type Props = {| - profilerData: ReactProfilerData, + profilerData: ReactProfilerDataV2, flamechart: FlamechartData, schedulerCanvasHeight: number, |}; @@ -96,6 +98,7 @@ const zoomToBatch = ( type AutoSizedCanvasProps = {| data: ReactProfilerData, + dataV2: ReactProfilerDataV2, flamechart: FlamechartData, height: number, schedulerCanvasHeight: number, @@ -104,6 +107,7 @@ type AutoSizedCanvasProps = {| function AutoSizedCanvas({ data, + dataV2, flamechart, height, schedulerCanvasHeight, diff --git a/src/ImportPage.js b/src/ImportPage.js index a7070fb3c8555..ea85f957791aa 100644 --- a/src/ImportPage.js +++ b/src/ImportPage.js @@ -1,11 +1,12 @@ // @flow import type {TimelineEvent} from './speedscope/import/chrome'; -import type {FlamechartData, ReactProfilerData} from './types'; +import type {FlamechartData, ReactProfilerDataV2} from './types'; import React, {useEffect} from 'react'; import preprocessData from './util/preprocessData'; +// import preprocessDataNew from './util/preprocessDataV2'; import preprocessFlamechart from './util/preprocessFlamechart'; // TODO: Add import button but keep a static path until canvas layout is ready @@ -13,7 +14,7 @@ import JSON_PATH from 'url:../static/small-devtools.json'; type Props = {| onDataImported: ( - profilerData: ReactProfilerData, + profilerData: ReactProfilerDataV2, flamechart: FlamechartData, ) => void, |}; @@ -29,6 +30,8 @@ export default function ImportPage({onDataImported}: Props) { events = events.filter(Boolean).sort((a, b) => (a.ts > b.ts ? 1 : -1)); if (events.length > 0) { + // TODO: Remove old preprocessData call + // const processedDataNew = preprocessDataNew(events); const processedData = preprocessData(events); const processedFlamechart = preprocessFlamechart(events); onDataImported(processedData, processedFlamechart); From 97b1543d07cac6c026db07bd4c9e4ab329118a38 Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Wed, 1 Jul 2020 07:26:03 +0800 Subject: [PATCH 026/116] Break renderCanvas into small render* functions (#27) --- src/CanvasPage.js | 2 +- src/canvas/canvasUtils.js | 6 +- src/canvas/renderCanvas.js | 517 ++++++++++++++++++++----------------- src/types.js | 2 +- src/util/usePanAndZoom.js | 25 +- 5 files changed, 306 insertions(+), 246 deletions(-) diff --git a/src/CanvasPage.js b/src/CanvasPage.js index 239933da2cfa8..e445946208099 100644 --- a/src/CanvasPage.js +++ b/src/CanvasPage.js @@ -144,7 +144,7 @@ function AutoSizedCanvas({ }); useLayoutEffect(() => { - if (data !== null) { + if (canvasRef.current !== null) { renderCanvas( data, flamechart, diff --git a/src/canvas/canvasUtils.js b/src/canvas/canvasUtils.js index 88064f0ed693e..37e7a56a1c544 100644 --- a/src/canvas/canvasUtils.js +++ b/src/canvas/canvasUtils.js @@ -110,8 +110,8 @@ export const trimFlamegraphText = ( export function getHoveredEvent( schedulerCanvasHeight: number, - data: ReactProfilerData, - flamechart: FlamechartData, + data: $ReadOnly, + flamechart: $ReadOnly, state: PanAndZoomState, ): ReactHoverContextInfo | null { const {canvasMouseX, canvasMouseY, offsetY} = state; @@ -238,7 +238,7 @@ export function getHoveredEvent( const cachedPriorityHeights = new Map(); export const getPriorityHeight = ( - data: ReactProfilerData, + data: $ReadOnly, priority: ReactPriority, ): number => { if (cachedPriorityHeights.has(priority)) { diff --git a/src/canvas/renderCanvas.js b/src/canvas/renderCanvas.js index ca9901b10f6d4..8a071b3311303 100644 --- a/src/canvas/renderCanvas.js +++ b/src/canvas/renderCanvas.js @@ -4,6 +4,8 @@ import type { ReactProfilerData, FlamechartData, ReactHoverContextInfo, + ReactEvent, + ReactMeasure, } from '../types'; import type {PanAndZoomState} from '../util/usePanAndZoom'; @@ -77,7 +79,90 @@ import { // '────────────────────────── // -const renderReact = ({ +function renderBackgroundFills(context, canvasWidth, canvasHeight) { + // Fill the canvas with the background color + context.fillStyle = COLORS.BACKGROUND; + context.fillRect(0, 0, canvasWidth, canvasHeight); +} + +/** + * Render all charting data (once it's loaded and processed) within the + * "scrollable" region. + */ +// TODO (windowing) We can avoid rendering all of this if we've scrolled some of it off screen. +function renderReactMarksAndMeasures( + context, + data, + state, + hoveredEvent, + canvasWidth, + canvasHeight, + canvasStartY, +) { + let priorityMinY = canvasStartY; + + REACT_PRIORITIES.forEach((priority, priorityIndex) => { + const currentPriority = data[priority]; + + let baseY = priorityMinY + REACT_GUTTER_SIZE; + + if (currentPriority.events.length > 0) { + currentPriority.events.forEach(event => { + const showHoverHighlight = hoveredEvent && hoveredEvent.event === event; + renderSingleReactMarkOrMeasure({ + baseY, + canvasWidth, + context, + eventOrMeasure: event, + showGroupHighlight: false, + showHoverHighlight, + priorityIndex, + state, + }); + }); + + // Draw the hovered and/or selected items on top so they stand out. + // This is helpful if there are multiple (overlapping) items close to each other. + if (hoveredEvent !== null && hoveredEvent.event !== null) { + renderSingleReactMarkOrMeasure({ + baseY, + canvasWidth, + context, + eventOrMeasure: hoveredEvent.event, + showGroupHighlight: false, + showHoverHighlight: true, + priorityIndex: hoveredEvent.priorityIndex, + state, + }); + } + + baseY += REACT_EVENT_SIZE + REACT_GUTTER_SIZE; + } + + currentPriority.measures.forEach(measure => { + const showHoverHighlight = + hoveredEvent && hoveredEvent.measure === measure; + const showGroupHighlight = + hoveredEvent && + hoveredEvent.measure !== null && + hoveredEvent.measure.batchUID === measure.batchUID; + renderSingleReactMarkOrMeasure({ + baseY, + canvasWidth, + context, + eventOrMeasure: measure, + priorityIndex, + showGroupHighlight, + showHoverHighlight, + state, + }); + }); + + priorityMinY += getPriorityHeight(data, priority); + }); +} + +function renderSingleReactMarkOrMeasure({ baseY, canvasWidth, context, @@ -86,7 +171,7 @@ const renderReact = ({ showGroupHighlight, showHoverHighlight, state, -}) => { +}) { const {timestamp, type} = eventOrMeasure; const {offsetY} = state; @@ -212,268 +297,234 @@ const renderReact = ({ console.warn(`Unexpected event or measure type "${type}"`); break; } -}; - -// TODO Passing "state" directly breaks memoization for e.g. mouse moves -export const renderCanvas = memoize( - ( - data: ReactProfilerData, - flamechart: FlamechartData | null, - canvas: HTMLCanvasElement | null, - canvasWidth: number, - canvasHeight: number, - schedulerCanvasHeight: number, - state: PanAndZoomState, - hoveredEvent: ReactHoverContextInfo | null, - ) => { - const {offsetX, offsetY, zoomLevel} = state; - - const context = getCanvasContext(canvas, canvasHeight, canvasWidth, true); +} - // Fill the canvas with the background color - context.fillStyle = COLORS.BACKGROUND; - context.fillRect(0, 0, canvasWidth, canvasHeight); - - // Charting data renders within this region of pixels as "scrollable" content. - // Time markers (top) and priority labels (left) are fixed content. - const scrollableCanvasWidth = canvasWidth - LABEL_FIXED_WIDTH; - - let y = 0; - - const interval = getTimeTickInterval(zoomLevel); - const intervalSize = interval * zoomLevel; - const firstIntervalPosition = - 0 - offsetX + Math.floor(offsetX / intervalSize) * intervalSize; - - // Render all charting data (once it's loaded and processed) within the "scrollable" region. - // TODO (windowing) We can avoid rendering all of this if we've scrolled some of it off screen. - if (data != null) { - // Time markers do not scroll off screen; they are always rendered at a fixed vertical position. - y = HEADER_HEIGHT_FIXED - offsetY; - - let priorityMinY = HEADER_HEIGHT_FIXED; - - REACT_PRIORITIES.forEach((priority, priorityIndex) => { - const currentPriority = data[priority]; - - let baseY = priorityMinY + REACT_GUTTER_SIZE; - - if (currentPriority.events.length > 0) { - currentPriority.events.forEach(event => { - const showHoverHighlight = - hoveredEvent && hoveredEvent.event === event; - renderReact({ - baseY, - canvasWidth, - context, - eventOrMeasure: event, - showGroupHighlight: false, - showHoverHighlight, - priorityIndex, - state, - }); - }); - - // Draw the hovered and/or selected items on top so they stand out. - // This is helpful if there are multiple (overlapping) items close to each other. - if (hoveredEvent !== null && hoveredEvent.event !== null) { - renderReact({ - baseY, - canvasWidth, - context, - eventOrMeasure: hoveredEvent.event, - showGroupHighlight: false, - showHoverHighlight: true, - priorityIndex: hoveredEvent.priorityIndex, - state, - }); - } - - baseY += REACT_EVENT_SIZE + REACT_GUTTER_SIZE; - } - - currentPriority.measures.forEach(measure => { - const showHoverHighlight = - hoveredEvent && hoveredEvent.measure === measure; - const showGroupHighlight = - hoveredEvent && - hoveredEvent.measure !== null && - hoveredEvent.measure.batchUID === measure.batchUID; - renderReact({ - baseY, - canvasWidth, - context, - eventOrMeasure: measure, - priorityIndex, - showGroupHighlight, - showHoverHighlight, - state, - }); - }); - - priorityMinY += getPriorityHeight(data, priority); - }); +function renderFlamechart( + context, + flamechart, + state, + hoveredEvent, + canvasWidth, + canvasHeight, + /** y coord on canvas to start painting at */ + canvasStartY, +) { + context.textAlign = 'left'; + context.textBaseline = 'middle'; + context.font = `${FLAMECHART_FONT_SIZE}px sans-serif`; + + for (let i = 0; i < flamechart.layers.length; i++) { + const nodes = flamechart.layers[i]; + + const layerY = Math.floor(canvasStartY + i * FLAMECHART_FRAME_HEIGHT); + if ( + layerY + FLAMECHART_FRAME_HEIGHT < HEADER_HEIGHT_FIXED || + canvasHeight < layerY + ) { + continue; // Not in view } - // Flame graph data renders below the prioritized React data. - // TODO Timestamp alignment is off by a few hundred me from our user timing marks; why? - if (flamechart !== null) { - context.textAlign = 'left'; - context.textBaseline = 'middle'; - context.font = `${FLAMECHART_FONT_SIZE}px sans-serif`; - - for (let i = 0; i < flamechart.layers.length; i++) { - const nodes = flamechart.layers[i]; - - const layerY = Math.floor( - HEADER_HEIGHT_FIXED + - schedulerCanvasHeight + - i * FLAMECHART_FRAME_HEIGHT - - offsetY, - ); - if ( - layerY + FLAMECHART_FRAME_HEIGHT < HEADER_HEIGHT_FIXED || - canvasHeight < layerY - ) { - continue; // Not in view - } + for (let j = 0; j < nodes.length; j++) { + const {end, node, start} = nodes[j]; + const {name} = node.frame; - for (let j = 0; j < nodes.length; j++) { - const {end, node, start} = nodes[j]; - const {name} = node.frame; + const showHoverHighlight = + hoveredEvent && hoveredEvent.flamechartNode === nodes[j]; - const showHoverHighlight = - hoveredEvent && hoveredEvent.flamechartNode === nodes[j]; + const width = durationToWidth((end - start) / 1000, state); + if (width <= 0) { + return; // Too small to render at this zoom level + } - const width = durationToWidth((end - start) / 1000, state); - if (width <= 0) { - return; // Too small to render at this zoom level - } + const x = Math.floor(timestampToPosition(start / 1000, state)); + if (x + width < 0 || canvasWidth < x) { + continue; // Not in view + } - const x = Math.floor(timestampToPosition(start / 1000, state)); - if (x + width < 0 || canvasWidth < x) { - continue; // Not in view - } + context.fillStyle = showHoverHighlight + ? COLORS.FLAME_GRAPH_HOVER + : COLORS.FLAME_GRAPH; - context.fillStyle = showHoverHighlight - ? COLORS.FLAME_GRAPH_HOVER - : COLORS.FLAME_GRAPH; + context.fillRect( + x, + layerY, + Math.floor(width - REACT_PRIORITY_BORDER_SIZE), + Math.floor(FLAMECHART_FRAME_HEIGHT - REACT_PRIORITY_BORDER_SIZE), + ); - context.fillRect( - x, - layerY, - Math.floor(width - REACT_PRIORITY_BORDER_SIZE), - Math.floor(FLAMECHART_FRAME_HEIGHT - REACT_PRIORITY_BORDER_SIZE), + if (width > FLAMECHART_TEXT_PADDING * 2) { + const trimmedName = trimFlamegraphText( + context, + name, + width - FLAMECHART_TEXT_PADDING * 2 + (x < 0 ? x : 0), + ); + if (trimmedName !== null) { + context.fillStyle = COLORS.PRIORITY_LABEL; + context.fillText( + trimmedName, + x + FLAMECHART_TEXT_PADDING - (x < 0 ? x : 0), + layerY + FLAMECHART_FRAME_HEIGHT / 2, ); - - if (width > FLAMECHART_TEXT_PADDING * 2) { - const trimmedName = trimFlamegraphText( - context, - name, - width - FLAMECHART_TEXT_PADDING * 2 + (x < 0 ? x : 0), - ); - if (trimmedName !== null) { - context.fillStyle = COLORS.PRIORITY_LABEL; - context.fillText( - trimmedName, - x + FLAMECHART_TEXT_PADDING - (x < 0 ? x : 0), - layerY + FLAMECHART_FRAME_HEIGHT / 2, - ); - } - } } } } + } +} - // LEFT: Priority labels - // Priority labels do not scroll off screen; they are always rendered at a fixed horizontal position. - // Render them last, on top of everything else, to account for things scrolled beneath them. - y = HEADER_HEIGHT_FIXED - offsetY; +function renderPriorityLabels(context, data, canvasWidth, canvasStartY) { + let y = canvasStartY; - REACT_PRIORITIES.forEach((priority, priorityIndex) => { - const priorityHeight = getPriorityHeight(data, priority); + REACT_PRIORITIES.forEach((priority, priorityIndex) => { + const priorityHeight = getPriorityHeight(data, priority); - if (priorityHeight === 0) { - return; - } + if (priorityHeight === 0) { + return; + } - context.fillStyle = COLORS.PRIORITY_BACKGROUND; - context.fillRect( - 0, - Math.floor(y), - Math.floor(LABEL_FIXED_WIDTH), - priorityHeight, - ); + context.fillStyle = COLORS.PRIORITY_BACKGROUND; + context.fillRect( + 0, + Math.floor(y), + Math.floor(LABEL_FIXED_WIDTH), + priorityHeight, + ); - context.fillStyle = COLORS.PRIORITY_BORDER; - context.fillRect( - 0, - Math.floor(y + priorityHeight), - canvasWidth, - REACT_PRIORITY_BORDER_SIZE, - ); + context.fillStyle = COLORS.PRIORITY_BORDER; + context.fillRect( + 0, + Math.floor(y + priorityHeight), + canvasWidth, + REACT_PRIORITY_BORDER_SIZE, + ); + + context.fillStyle = COLORS.PRIORITY_BORDER; + context.fillRect( + Math.floor(LABEL_FIXED_WIDTH) - REACT_PRIORITY_BORDER_SIZE, + Math.floor(y), + REACT_PRIORITY_BORDER_SIZE, + priorityHeight, + ); + + context.fillStyle = COLORS.PRIORITY_LABEL; + context.textAlign = 'left'; + context.textBaseline = 'middle'; + context.font = `${LABEL_FONT_SIZE}px sans-serif`; + context.fillText(priority, 4, y + priorityHeight / 2); + + y += priorityHeight + REACT_PRIORITY_BORDER_SIZE; + }); +} + +function renderAxisMarkers( + context, + state, + canvasWidth, + panOffsetX, + panZoomLevel, +) { + context.fillStyle = COLORS.BACKGROUND; + context.fillRect(0, 0, canvasWidth, HEADER_HEIGHT_FIXED); + + context.fillStyle = COLORS.PRIORITY_BORDER; + context.fillRect(0, MARKER_HEIGHT, canvasWidth, REACT_PRIORITY_BORDER_SIZE); + + // Charting data renders within this region of pixels as "scrollable" content. + // Time markers (top) and priority labels (left) are fixed content. + const scrollableCanvasWidth = canvasWidth - LABEL_FIXED_WIDTH; + + const interval = getTimeTickInterval(panZoomLevel); + const intervalSize = interval * panZoomLevel; + const firstIntervalPosition = + 0 - panOffsetX + Math.floor(panOffsetX / intervalSize) * intervalSize; + + for ( + let i = firstIntervalPosition; + i < scrollableCanvasWidth; + i += intervalSize + ) { + if (i > 0) { + const markerTimestamp = positionToTimestamp(i + LABEL_FIXED_WIDTH, state); + const markerLabel = Math.round(markerTimestamp); + + const x = LABEL_FIXED_WIDTH + i; context.fillStyle = COLORS.PRIORITY_BORDER; context.fillRect( - Math.floor(LABEL_FIXED_WIDTH) - REACT_PRIORITY_BORDER_SIZE, - Math.floor(y), + x, + MARKER_HEIGHT - MARKER_TICK_HEIGHT, REACT_PRIORITY_BORDER_SIZE, - priorityHeight, + MARKER_TICK_HEIGHT, ); - context.fillStyle = COLORS.PRIORITY_LABEL; - context.textAlign = 'left'; + context.fillStyle = COLORS.TIME_MARKER_LABEL; + context.textAlign = 'right'; context.textBaseline = 'middle'; - context.font = `${LABEL_FONT_SIZE}px sans-serif`; - context.fillText(priority, 4, y + priorityHeight / 2); - - y += priorityHeight + REACT_PRIORITY_BORDER_SIZE; - }); + context.font = `${MARKER_FONT_SIZE}px sans-serif`; + context.fillText( + `${markerLabel}ms`, + x - MARKER_TEXT_PADDING, + MARKER_HEIGHT / 2, + ); + } + } +} - // TOP: Time markers - // Time markers do not scroll off screen; they are always rendered at a fixed vertical position. - // Render them last, on top of everything else, to account for things scrolled beneath them. - y = 0; +// TODO Passing "state" directly breaks memoization for e.g. mouse moves +export const renderCanvas = memoize( + ( + data: $ReadOnly, + flamechart: $ReadOnly, + canvas: HTMLCanvasElement, + canvasWidth: number, + canvasHeight: number, + /** Precomputed height of marks and measures canvas section */ + schedulerCanvasHeight: number, // TODO: Figure out why this can't be calculated here + state: $ReadOnly, + hoveredEvent: $ReadOnly | null, + ) => { + const {offsetX, offsetY, zoomLevel} = state; - context.fillStyle = COLORS.BACKGROUND; - context.fillRect(0, 0, canvasWidth, HEADER_HEIGHT_FIXED); + const context = getCanvasContext(canvas, canvasHeight, canvasWidth, true); - context.fillStyle = COLORS.PRIORITY_BORDER; - context.fillRect(0, MARKER_HEIGHT, canvasWidth, REACT_PRIORITY_BORDER_SIZE); + renderBackgroundFills(context, canvasWidth, canvasHeight); - // Draw time marker text on top of the priority groupings - for ( - let i = firstIntervalPosition; - i < scrollableCanvasWidth; - i += intervalSize - ) { - if (i > 0) { - const markerTimestamp = positionToTimestamp( - i + LABEL_FIXED_WIDTH, - state, - ); - const markerLabel = Math.round(markerTimestamp); + renderReactMarksAndMeasures( + context, + data, + state, + hoveredEvent, + canvasWidth, + canvasHeight, + // Time markers do not scroll off screen; they are always rendered at a + // fixed vertical position. + HEADER_HEIGHT_FIXED, + ); - const x = LABEL_FIXED_WIDTH + i; + // Flame graph data renders below the prioritized React data. + // TODO Timestamp alignment is off by a few hundred me from our user timing marks; why? + renderFlamechart( + context, + flamechart, + state, + hoveredEvent, + canvasWidth, + canvasHeight, + HEADER_HEIGHT_FIXED + schedulerCanvasHeight - offsetY, + ); - context.fillStyle = COLORS.PRIORITY_BORDER; - context.fillRect( - x, - MARKER_HEIGHT - MARKER_TICK_HEIGHT, - REACT_PRIORITY_BORDER_SIZE, - MARKER_TICK_HEIGHT, - ); + // LEFT: Priority labels + // Render them last, on top of everything else, to account for things scrolled beneath them. + renderPriorityLabels( + context, + data, + canvasWidth, + HEADER_HEIGHT_FIXED - offsetY, + ); - context.fillStyle = COLORS.TIME_MARKER_LABEL; - context.textAlign = 'right'; - context.textBaseline = 'middle'; - context.font = `${MARKER_FONT_SIZE}px sans-serif`; - context.fillText( - `${markerLabel}ms`, - x - MARKER_TEXT_PADDING, - MARKER_HEIGHT / 2, - ); - } - } + // TOP: Time markers + // Time markers do not scroll off screen; they are always rendered at a fixed vertical position. + // Render them last, on top of everything else, to account for things scrolled beneath them. + // Draw time marker text on top of the priority groupings + renderAxisMarkers(context, state, canvasWidth, offsetX, zoomLevel); }, ); diff --git a/src/types.js b/src/types.js index 03c972e7ab278..ea2e255ab101a 100644 --- a/src/types.js +++ b/src/types.js @@ -79,7 +79,7 @@ export type ReactHoverContextInfo = {| /** @deprecated */ priorityIndex: number | null, /** @deprecated */ - data: ReactProfilerData | null, + data: $ReadOnly | null, flamechartNode: FlamechartFrame | null, |}; diff --git a/src/util/usePanAndZoom.js b/src/util/usePanAndZoom.js index 9df8dd898cd62..c14df88739114 100644 --- a/src/util/usePanAndZoom.js +++ b/src/util/usePanAndZoom.js @@ -46,23 +46,32 @@ const initialState: PanAndZoomState = { }; // TODO Account for fixed label width -export function positionToTimestamp(position: number, state: PanAndZoomState) { +export function positionToTimestamp( + position: number, + state: $ReadOnly, +) { return (position - state.fixedColumnWidth + state.offsetX) / state.zoomLevel; } // TODO Account for fixed label width -export function timestampToPosition(timestamp: number, state: PanAndZoomState) { +export function timestampToPosition( + timestamp: number, + state: $ReadOnly, +) { return timestamp * state.zoomLevel + state.fixedColumnWidth - state.offsetX; } -export function durationToWidth(duration: number, state: PanAndZoomState) { +export function durationToWidth( + duration: number, + state: $ReadOnly, +) { return Math.max( duration * state.zoomLevel - BAR_HORIZONTAL_SPACING, MIN_BAR_WIDTH, ); } -function getMaxOffsetX(state: PanAndZoomState) { +function getMaxOffsetX(state: $ReadOnly) { return ( state.unscaledContentWidth * state.zoomLevel - state.canvasWidth + @@ -70,7 +79,7 @@ function getMaxOffsetX(state: PanAndZoomState) { ); } -function getMaxOffsetY(state: PanAndZoomState) { +function getMaxOffsetY(state: $ReadOnly) { return ( state.unscaledContentHeight - state.canvasHeight + state.fixedHeaderHeight ); @@ -78,7 +87,7 @@ function getMaxOffsetY(state: PanAndZoomState) { type InitializeAction = {| type: 'initialize', - payload: $Shape, + payload: $Shape, |}; type MouseDownAction = {| type: 'mouse-down', @@ -133,7 +142,7 @@ function reducer( zoomLevel: payload.zoomLevel, offsetX: clamp(0, getMaxOffsetX(state), state.offsetX), offsetY: clamp(0, getMaxOffsetY(state), state.offsetY), - }: State); + }: PanAndZoomState); } case 'mouse-down': { return { @@ -199,7 +208,7 @@ function reducer( if (absDeltaY > ZOOM_WHEEL_DELTA_THRESHOLD) { const {canvasMouseX} = getCanvasMousePos(canvas, event); - const nextState = { + const nextState: PanAndZoomState = { ...state, zoomLevel: clamp( minZoomLevel, From a99e7670b0cfd7c0a7c998179f7b463029aecb5e Mon Sep 17 00:00:00 2001 From: Kartik Choudhary Date: Wed, 1 Jul 2020 14:46:28 +0530 Subject: [PATCH 027/116] Separate v1 v2 data --- src/App.js | 42 +++++++++++++++++++++++++++++++++++++----- src/CanvasPage.js | 14 ++++++++++---- src/ImportPage.js | 34 +++++++++++++++++++++++++++++----- 3 files changed, 76 insertions(+), 14 deletions(-) diff --git a/src/App.js b/src/App.js index e9e3306e2ee95..2994025cee54f 100644 --- a/src/App.js +++ b/src/App.js @@ -1,6 +1,10 @@ // @flow -import type {FlamechartData, ReactProfilerDataV2} from './types'; +import type { + FlamechartData, + ReactProfilerData, + ReactProfilerDataV2, +} from './types'; import React, {useState, useCallback} from 'react'; import {unstable_batchedUpdates} from 'react-dom'; @@ -11,15 +15,19 @@ import ImportPage from './ImportPage'; import CanvasPage from './CanvasPage'; export default function App() { - const [profilerData, setProfilerData] = useState( + const [profilerData, setProfilerData] = useState( null, ); + const [ + profilerDataV2, + setProfilerDataV2, + ] = useState(null); const [flamechart, setFlamechart] = useState(null); const [schedulerCanvasHeight, setSchedulerCanvasHeight] = useState(0); const handleDataImported = useCallback( ( - importedProfilerData: ReactProfilerDataV2, + importedProfilerData: ReactProfilerData, importedFlamechart: FlamechartData, ) => { unstable_batchedUpdates(() => { @@ -34,15 +42,39 @@ export default function App() { }, ); - if (profilerData && flamechart) { + // TODO: Migrate and completely remove V2 stuff + const handleDataImportedV2 = useCallback( + ( + importedProfilerData: ReactProfilerDataV2, + importedFlamechart: FlamechartData, + ) => { + unstable_batchedUpdates(() => { + setSchedulerCanvasHeight( + REACT_PRIORITIES.reduce((height, priority) => { + return height + getPriorityHeight(importedProfilerData, priority); + }, 0), + ); + setProfilerDataV2(importedProfilerData); + setFlamechart(importedFlamechart); + }); + }, + ); + + if (profilerData && profilerDataV2 && flamechart) { return ( ); } else { - return ; + return ( + + ); } } diff --git a/src/CanvasPage.js b/src/CanvasPage.js index c37707f1e2de2..d755987657e0f 100644 --- a/src/CanvasPage.js +++ b/src/CanvasPage.js @@ -35,19 +35,24 @@ import type { type ContextMenuContextData = {| data: ReactProfilerData, - dataV2: ReactProfilerDataV2, flamechart: FlamechartData, hoveredEvent: ReactHoverContextInfo | null, state: PanAndZoomState, |}; type Props = {| - profilerData: ReactProfilerDataV2, + profilerData: ReactProfilerData, + profilerDataV2: ReactProfilerDataV2, flamechart: FlamechartData, schedulerCanvasHeight: number, |}; -function CanvasPage({profilerData, flamechart, schedulerCanvasHeight}: Props) { +function CanvasPage({ + profilerData, + profilerDataV2, + flamechart, + schedulerCanvasHeight, +}: Props) { return (
( void, + onDataImportedV2: ( profilerData: ReactProfilerDataV2, flamechart: FlamechartData, ) => void, |}; -export default function ImportPage({onDataImported}: Props) { +export default function ImportPage({onDataImported, onDataImportedV2}: Props) { useEffect(() => { fetch(JSON_PATH) .then(res => res.json()) @@ -30,8 +39,6 @@ export default function ImportPage({onDataImported}: Props) { events = events.filter(Boolean).sort((a, b) => (a.ts > b.ts ? 1 : -1)); if (events.length > 0) { - // TODO: Remove old preprocessData call - // const processedDataNew = preprocessDataNew(events); const processedData = preprocessData(events); const processedFlamechart = preprocessFlamechart(events); onDataImported(processedData, processedFlamechart); @@ -39,6 +46,23 @@ export default function ImportPage({onDataImported}: Props) { }); }, []); + useEffect(() => { + fetch(JSON_PATHV2) + .then(res => res.json()) + .then((events: TimelineEvent[]) => { + // Filter null entries and sort by timestamp. + // I would not expect to have to do either of this, + // but some of the data being passed in requires it. + events = events.filter(Boolean).sort((a, b) => (a.ts > b.ts ? 1 : -1)); + + if (events.length > 0) { + const processedData = preprocessDataV2(events); + const processedFlamechart = preprocessFlamechart(events); + onDataImportedV2(processedData, processedFlamechart); + } + }); + }, []); + return (
LOADING. TODO: Turn this into an import page. This page currently just From cba77ba60ad715068a442bf0567c57368ea4b546 Mon Sep 17 00:00:00 2001 From: Kartik Choudhary Date: Thu, 2 Jul 2020 06:44:39 +0000 Subject: [PATCH 028/116] Remove setSchedulerCanvasHeight Co-authored-by: E-Liang Tan --- src/App.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/App.js b/src/App.js index 2994025cee54f..6ad892d4f9728 100644 --- a/src/App.js +++ b/src/App.js @@ -49,11 +49,6 @@ export default function App() { importedFlamechart: FlamechartData, ) => { unstable_batchedUpdates(() => { - setSchedulerCanvasHeight( - REACT_PRIORITIES.reduce((height, priority) => { - return height + getPriorityHeight(importedProfilerData, priority); - }, 0), - ); setProfilerDataV2(importedProfilerData); setFlamechart(importedFlamechart); }); From 02748cc6441bb9f4d0068b083e8ffbb1c7277357 Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Fri, 3 Jul 2020 10:35:03 +0800 Subject: [PATCH 029/116] [Canvas V2][1/n] Implement display of measures (#31) --- src/CanvasPage.js | 3 +- src/canvas/canvasUtils.js | 17 +- src/canvas/constants.js | 2 +- src/canvas/renderCanvas.js | 551 +++++++++++++++++++++---------------- 4 files changed, 334 insertions(+), 239 deletions(-) diff --git a/src/CanvasPage.js b/src/CanvasPage.js index 87aeea6930e2a..f91345dfc5f2a 100644 --- a/src/CanvasPage.js +++ b/src/CanvasPage.js @@ -156,12 +156,11 @@ function AutoSizedCanvas({ useLayoutEffect(() => { if (canvasRef.current !== null) { renderCanvas( - data, + dataV2, flamechart, canvasRef.current, width, height, - schedulerCanvasHeight, state, hoveredEvent, ); diff --git a/src/canvas/canvasUtils.js b/src/canvas/canvasUtils.js index 37e7a56a1c544..fde69fbffc340 100644 --- a/src/canvas/canvasUtils.js +++ b/src/canvas/canvasUtils.js @@ -2,10 +2,12 @@ // Contains helper functions for rendering canvas elements import type { - ReactProfilerData, FlamechartData, ReactHoverContextInfo, + ReactLane, ReactPriority, + ReactProfilerData, + ReactProfilerDataV2, } from '../types'; import type {PanAndZoomState} from '../util/usePanAndZoom'; @@ -275,3 +277,16 @@ export const getPriorityHeight = ( return priorityHeight; } }; + +export const getLaneHeight = ( + data: $ReadOnly, + lane: ReactLane, +): number => { + // TODO: Return 0 if data has no data for lane + return ( + REACT_GUTTER_SIZE + + REACT_WORK_SIZE + + REACT_GUTTER_SIZE + + REACT_PRIORITY_BORDER_SIZE + ); +}; diff --git a/src/canvas/constants.js b/src/canvas/constants.js index 282b79a0a758d..8dccfd0558e87 100644 --- a/src/canvas/constants.js +++ b/src/canvas/constants.js @@ -44,7 +44,7 @@ export const TEXT_CSS_PIXELS_OFFSET_TOP = 11; export const FONT_SIZE = 10; export const BORDER_OPACITY = 0.4; -export const REACT_GUTTER_SIZE = 4; +export const REACT_GUTTER_SIZE = 0; export const REACT_EVENT_SIZE = 6; export const REACT_WORK_SIZE = 12; export const REACT_EVENT_BORDER_SIZE = 1; diff --git a/src/canvas/renderCanvas.js b/src/canvas/renderCanvas.js index 8a071b3311303..ef117f939e20f 100644 --- a/src/canvas/renderCanvas.js +++ b/src/canvas/renderCanvas.js @@ -1,11 +1,10 @@ // @flow import type { - ReactProfilerData, FlamechartData, ReactHoverContextInfo, - ReactEvent, - ReactMeasure, + ReactLane, + ReactProfilerDataV2, } from '../types'; import type {PanAndZoomState} from '../util/usePanAndZoom'; @@ -21,20 +20,16 @@ import { getCanvasContext, getTimeTickInterval, trimFlamegraphText, - getPriorityHeight, + getLaneHeight, } from './canvasUtils'; import { COLORS, - EVENT_SIZE, - LABEL_FONT_SIZE, MARKER_FONT_SIZE, MARKER_TEXT_PADDING, MARKER_HEIGHT, MARKER_TICK_HEIGHT, - REACT_PRIORITIES, REACT_GUTTER_SIZE, - REACT_EVENT_SIZE, REACT_WORK_SIZE, REACT_PRIORITY_BORDER_SIZE, FLAMECHART_FONT_SIZE, @@ -43,6 +38,7 @@ import { LABEL_FIXED_WIDTH, HEADER_HEIGHT_FIXED, } from './constants'; +import {REACT_TOTAL_NUM_LANES} from '../constants'; // The canvas we're rendering looks a little like the outline below. // Left labels mark different scheduler REACT_PRIORITIES, @@ -98,207 +94,294 @@ function renderReactMarksAndMeasures( canvasWidth, canvasHeight, canvasStartY, -) { - let priorityMinY = canvasStartY; - - REACT_PRIORITIES.forEach((priority, priorityIndex) => { - const currentPriority = data[priority]; - - let baseY = priorityMinY + REACT_GUTTER_SIZE; - - if (currentPriority.events.length > 0) { - currentPriority.events.forEach(event => { - const showHoverHighlight = hoveredEvent && hoveredEvent.event === event; - renderSingleReactMarkOrMeasure({ - baseY, - canvasWidth, +): number { + // TODO: Compute lanes to render from data? Or just use getLaneHeight to skip lanes + const lanesToRender: ReactLane[] = Array.from( + Array(REACT_TOTAL_NUM_LANES).keys(), + ); + + let laneMinY = canvasStartY; + + lanesToRender.forEach(lane => { + const baseY = laneMinY + REACT_GUTTER_SIZE; + + // TODO: Draw a separate event gutter. Split into a renderReactMarks function? + // if (data.events.length > 0) { + // data.events.forEach(event => { + // const showHoverHighlight = hoveredEvent && hoveredEvent.event === event; + // renderSingleReactMarkOrMeasure({ + // baseY, + // canvasWidth, + // context, + // eventOrMeasure: event, + // showGroupHighlight: false, + // showHoverHighlight, + // state, + // }); + // }); + + // // Draw the hovered and/or selected items on top so they stand out. + // // This is helpful if there are multiple (overlapping) items close to each other. + // // if (hoveredEvent !== null && hoveredEvent.event !== null) { + // // renderSingleReactMarkOrMeasure({ + // // baseY, + // // canvasWidth, + // // context, + // // eventOrMeasure: hoveredEvent.event, + // // showGroupHighlight: false, + // // showHoverHighlight: true, + // // state, + // // }); + // // } + + // baseY += REACT_EVENT_SIZE + REACT_GUTTER_SIZE; + // } + + data.measures + // TODO: Optimization: precompute this so that we don't filter this array |lanesToRender| times + .filter(measure => measure.lanes.includes(lane)) + .forEach(measure => { + const showHoverHighlight = + hoveredEvent && hoveredEvent.measure === measure; + const showGroupHighlight = + hoveredEvent && + hoveredEvent.measure && + hoveredEvent.measure.batchUID === measure.batchUID; + renderSingleReactMeasure( context, - eventOrMeasure: event, - showGroupHighlight: false, - showHoverHighlight, - priorityIndex, state, - }); - }); - - // Draw the hovered and/or selected items on top so they stand out. - // This is helpful if there are multiple (overlapping) items close to each other. - if (hoveredEvent !== null && hoveredEvent.event !== null) { - renderSingleReactMarkOrMeasure({ - baseY, + measure, canvasWidth, - context, - eventOrMeasure: hoveredEvent.event, - showGroupHighlight: false, - showHoverHighlight: true, - priorityIndex: hoveredEvent.priorityIndex, - state, - }); - } - - baseY += REACT_EVENT_SIZE + REACT_GUTTER_SIZE; - } - - currentPriority.measures.forEach(measure => { - const showHoverHighlight = - hoveredEvent && hoveredEvent.measure === measure; - const showGroupHighlight = - hoveredEvent && - hoveredEvent.measure !== null && - hoveredEvent.measure.batchUID === measure.batchUID; - renderSingleReactMarkOrMeasure({ - baseY, - canvasWidth, - context, - eventOrMeasure: measure, - priorityIndex, - showGroupHighlight, - showHoverHighlight, - state, + baseY, + showGroupHighlight, + showHoverHighlight, + ); }); - }); - priorityMinY += getPriorityHeight(data, priority); + laneMinY += getLaneHeight(data, lane); }); + + return laneMinY; } -function renderSingleReactMarkOrMeasure({ - baseY, - canvasWidth, +/** + * Render a single `ReactMeasure` as a bar in the canvas. + * + * @see renderReactMeasures + */ +function renderSingleReactMeasure( context, - eventOrMeasure, - priorityIndex, + state, + measure, + canvasWidth, + baseY, showGroupHighlight, showHoverHighlight, - state, -}) { - const {timestamp, type} = eventOrMeasure; +) { + const {timestamp, type, duration} = measure; const {offsetY} = state; let fillStyle = null; let hoveredFillStyle = null; let groupSelectedFillStyle = null; - let x, y, width; + + // We could change the max to 0 and just skip over rendering anything that small, + // but this has the effect of making the chart look very empty when zoomed out. + // So long as perf is okay- it might be best to err on the side of showing things. + const width = durationToWidth(duration, state); + if (width <= 0) { + return; // Too small to render at this zoom level + } + + const x = timestampToPosition(timestamp, state); + if (x + width < 0 || canvasWidth < x) { + return; // Not in view + } switch (type) { case 'commit': + fillStyle = COLORS.REACT_COMMIT; + hoveredFillStyle = COLORS.REACT_COMMIT_HOVER; + groupSelectedFillStyle = COLORS.REACT_COMMIT_SELECTED; + break; case 'render-idle': + // We could render idle time as diagonal hashes. + // This looks nicer when zoomed in, but not so nice when zoomed out. + // color = context.createPattern(getIdlePattern(), 'repeat'); + fillStyle = COLORS.REACT_IDLE; + hoveredFillStyle = COLORS.REACT_IDLE_HOVER; + groupSelectedFillStyle = COLORS.REACT_IDLE_SELECTED; + break; case 'render': + fillStyle = COLORS.REACT_RENDER; + hoveredFillStyle = COLORS.REACT_RENDER_HOVER; + groupSelectedFillStyle = COLORS.REACT_RENDER_SELECTED; + break; case 'layout-effects': - case 'passive-effects': - const {depth, duration} = ((eventOrMeasure: any): ReactMeasure); - - // We could change the max to 0 and just skip over rendering anything that small, - // but this has the effect of making the chart look very empty when zoomed out. - // So long as perf is okay- it might be best to err on the side of showing things. - width = durationToWidth(duration, state); - if (width <= 0) { - return; // Too small to render at this zoom level - } - - x = timestampToPosition(timestamp, state); - if (x + width < 0 || canvasWidth < x) { - return; // Not in view - } - - switch (type) { - case 'commit': - fillStyle = COLORS.REACT_COMMIT; - hoveredFillStyle = COLORS.REACT_COMMIT_HOVER; - groupSelectedFillStyle = COLORS.REACT_COMMIT_SELECTED; - break; - case 'render-idle': - // We could render idle time as diagonal hashes. - // This looks nicer when zoomed in, but not so nice when zoomed out. - // color = context.createPattern(getIdlePattern(), 'repeat'); - fillStyle = COLORS.REACT_IDLE; - hoveredFillStyle = COLORS.REACT_IDLE_HOVER; - groupSelectedFillStyle = COLORS.REACT_IDLE_SELECTED; - break; - case 'render': - fillStyle = COLORS.REACT_RENDER; - hoveredFillStyle = COLORS.REACT_RENDER_HOVER; - groupSelectedFillStyle = COLORS.REACT_RENDER_SELECTED; - break; - case 'layout-effects': - fillStyle = COLORS.REACT_LAYOUT_EFFECTS; - hoveredFillStyle = COLORS.REACT_LAYOUT_EFFECTS_HOVER; - groupSelectedFillStyle = COLORS.REACT_LAYOUT_EFFECTS_SELECTED; - break; - case 'passive-effects': - fillStyle = COLORS.REACT_PASSIVE_EFFECTS; - hoveredFillStyle = COLORS.REACT_PASSIVE_EFFECTS_HOVER; - groupSelectedFillStyle = COLORS.REACT_PASSIVE_EFFECTS_SELECTED; - break; - default: - console.warn(`Unexpected type "${type}"`); - break; - } - - y = baseY + REACT_WORK_SIZE * depth + REACT_GUTTER_SIZE * depth - offsetY; - - // $FlowFixMe We know these won't be null - context.fillStyle = showHoverHighlight - ? hoveredFillStyle - : showGroupHighlight - ? groupSelectedFillStyle - : fillStyle; - context.fillRect( - Math.floor(x), - Math.floor(y), - Math.floor(width), - REACT_WORK_SIZE, - ); + fillStyle = COLORS.REACT_LAYOUT_EFFECTS; + hoveredFillStyle = COLORS.REACT_LAYOUT_EFFECTS_HOVER; + groupSelectedFillStyle = COLORS.REACT_LAYOUT_EFFECTS_SELECTED; break; - case 'schedule-render': - case 'schedule-state-update': - case 'suspend': - const {isCascading} = ((eventOrMeasure: any): ReactEvent); - - x = timestampToPosition(timestamp, state); - if (x + EVENT_SIZE / 2 < 0 || canvasWidth < x) { - return; // Not in view - } - - switch (type) { - case 'schedule-render': - case 'schedule-state-update': - if (isCascading) { - fillStyle = showHoverHighlight - ? COLORS.REACT_SCHEDULE_CASCADING_HOVER - : COLORS.REACT_SCHEDULE_CASCADING; - } else { - fillStyle = showHoverHighlight - ? COLORS.REACT_SCHEDULE_HOVER - : COLORS.REACT_SCHEDULE; - } - break; - case 'suspend': - fillStyle = showHoverHighlight - ? COLORS.REACT_SUSPEND_HOVER - : COLORS.REACT_SUSPEND; - break; - default: - console.warn(`Unexpected event or measure type "${type}"`); - break; - } - - if (fillStyle !== null) { - const circumference = REACT_EVENT_SIZE; - y = baseY + REACT_EVENT_SIZE / 2 - offsetY; - - context.beginPath(); - context.fillStyle = fillStyle; - context.arc(x, y, circumference / 2, 0, 2 * Math.PI); - context.fill(); - } + case 'passive-effects': + fillStyle = COLORS.REACT_PASSIVE_EFFECTS; + hoveredFillStyle = COLORS.REACT_PASSIVE_EFFECTS_HOVER; + groupSelectedFillStyle = COLORS.REACT_PASSIVE_EFFECTS_SELECTED; break; default: - console.warn(`Unexpected event or measure type "${type}"`); - break; + throw new Error(`Unexpected measure type "${type}"`); } + + const y = baseY - offsetY; + + context.fillStyle = showHoverHighlight + ? hoveredFillStyle + : showGroupHighlight + ? groupSelectedFillStyle + : fillStyle; + context.fillRect( + Math.floor(x), + Math.floor(y), + Math.floor(width), + REACT_WORK_SIZE, + ); } +// function renderSingleReactMarkOrMeasure({ +// baseY, +// canvasWidth, +// context, +// eventOrMeasure, +// showGroupHighlight, +// showHoverHighlight, +// state, +// }) { +// const {timestamp, type} = eventOrMeasure; +// const {offsetY} = state; + +// let fillStyle = null; +// let hoveredFillStyle = null; +// let groupSelectedFillStyle = null; +// let x, y, width; + +// switch (type) { +// case 'commit': +// case 'render-idle': +// case 'render': +// case 'layout-effects': +// case 'passive-effects': +// const {depth, duration} = ((eventOrMeasure: any): ReactMeasure); + +// // We could change the max to 0 and just skip over rendering anything that small, +// // but this has the effect of making the chart look very empty when zoomed out. +// // So long as perf is okay- it might be best to err on the side of showing things. +// width = durationToWidth(duration, state); +// if (width <= 0) { +// return; // Too small to render at this zoom level +// } + +// x = timestampToPosition(timestamp, state); +// if (x + width < 0 || canvasWidth < x) { +// return; // Not in view +// } + +// switch (type) { +// case 'commit': +// fillStyle = COLORS.REACT_COMMIT; +// hoveredFillStyle = COLORS.REACT_COMMIT_HOVER; +// groupSelectedFillStyle = COLORS.REACT_COMMIT_SELECTED; +// break; +// case 'render-idle': +// // We could render idle time as diagonal hashes. +// // This looks nicer when zoomed in, but not so nice when zoomed out. +// // color = context.createPattern(getIdlePattern(), 'repeat'); +// fillStyle = COLORS.REACT_IDLE; +// hoveredFillStyle = COLORS.REACT_IDLE_HOVER; +// groupSelectedFillStyle = COLORS.REACT_IDLE_SELECTED; +// break; +// case 'render': +// fillStyle = COLORS.REACT_RENDER; +// hoveredFillStyle = COLORS.REACT_RENDER_HOVER; +// groupSelectedFillStyle = COLORS.REACT_RENDER_SELECTED; +// break; +// case 'layout-effects': +// fillStyle = COLORS.REACT_LAYOUT_EFFECTS; +// hoveredFillStyle = COLORS.REACT_LAYOUT_EFFECTS_HOVER; +// groupSelectedFillStyle = COLORS.REACT_LAYOUT_EFFECTS_SELECTED; +// break; +// case 'passive-effects': +// fillStyle = COLORS.REACT_PASSIVE_EFFECTS; +// hoveredFillStyle = COLORS.REACT_PASSIVE_EFFECTS_HOVER; +// groupSelectedFillStyle = COLORS.REACT_PASSIVE_EFFECTS_SELECTED; +// break; +// default: +// console.warn(`Unexpected type "${type}"`); +// break; +// } + +// y = baseY + REACT_WORK_SIZE * depth + REACT_GUTTER_SIZE * depth - offsetY; + +// // $FlowFixMe We know these won't be null +// context.fillStyle = showHoverHighlight +// ? hoveredFillStyle +// : showGroupHighlight +// ? groupSelectedFillStyle +// : fillStyle; +// context.fillRect( +// Math.floor(x), +// Math.floor(y), +// Math.floor(width), +// REACT_WORK_SIZE, +// ); +// break; +// case 'schedule-render': +// case 'schedule-state-update': +// case 'suspend': +// const {isCascading} = ((eventOrMeasure: any): ReactEvent); + +// x = timestampToPosition(timestamp, state); +// if (x + EVENT_SIZE / 2 < 0 || canvasWidth < x) { +// return; // Not in view +// } + +// switch (type) { +// case 'schedule-render': +// case 'schedule-state-update': +// if (isCascading) { +// fillStyle = showHoverHighlight +// ? COLORS.REACT_SCHEDULE_CASCADING_HOVER +// : COLORS.REACT_SCHEDULE_CASCADING; +// } else { +// fillStyle = showHoverHighlight +// ? COLORS.REACT_SCHEDULE_HOVER +// : COLORS.REACT_SCHEDULE; +// } +// break; +// case 'suspend': +// fillStyle = showHoverHighlight +// ? COLORS.REACT_SUSPEND_HOVER +// : COLORS.REACT_SUSPEND; +// break; +// default: +// console.warn(`Unexpected event or measure type "${type}"`); +// break; +// } + +// if (fillStyle !== null) { +// const circumference = REACT_EVENT_SIZE; +// y = baseY + REACT_EVENT_SIZE / 2 - offsetY; + +// context.beginPath(); +// context.fillStyle = fillStyle; +// context.arc(x, y, circumference / 2, 0, 2 * Math.PI); +// context.fill(); +// } +// break; +// default: +// console.warn(`Unexpected event or measure type "${type}"`); +// break; +// } +// } + function renderFlamechart( context, flamechart, @@ -371,49 +454,49 @@ function renderFlamechart( } } -function renderPriorityLabels(context, data, canvasWidth, canvasStartY) { - let y = canvasStartY; - - REACT_PRIORITIES.forEach((priority, priorityIndex) => { - const priorityHeight = getPriorityHeight(data, priority); - - if (priorityHeight === 0) { - return; - } - - context.fillStyle = COLORS.PRIORITY_BACKGROUND; - context.fillRect( - 0, - Math.floor(y), - Math.floor(LABEL_FIXED_WIDTH), - priorityHeight, - ); - - context.fillStyle = COLORS.PRIORITY_BORDER; - context.fillRect( - 0, - Math.floor(y + priorityHeight), - canvasWidth, - REACT_PRIORITY_BORDER_SIZE, - ); - - context.fillStyle = COLORS.PRIORITY_BORDER; - context.fillRect( - Math.floor(LABEL_FIXED_WIDTH) - REACT_PRIORITY_BORDER_SIZE, - Math.floor(y), - REACT_PRIORITY_BORDER_SIZE, - priorityHeight, - ); - - context.fillStyle = COLORS.PRIORITY_LABEL; - context.textAlign = 'left'; - context.textBaseline = 'middle'; - context.font = `${LABEL_FONT_SIZE}px sans-serif`; - context.fillText(priority, 4, y + priorityHeight / 2); - - y += priorityHeight + REACT_PRIORITY_BORDER_SIZE; - }); -} +// function renderPriorityLabels(context, data, canvasWidth, canvasStartY) { +// let y = canvasStartY; + +// REACT_PRIORITIES.forEach((priority, priorityIndex) => { +// const priorityHeight = getPriorityHeight(data, priority); + +// if (priorityHeight === 0) { +// return; +// } + +// context.fillStyle = COLORS.PRIORITY_BACKGROUND; +// context.fillRect( +// 0, +// Math.floor(y), +// Math.floor(LABEL_FIXED_WIDTH), +// priorityHeight, +// ); + +// context.fillStyle = COLORS.PRIORITY_BORDER; +// context.fillRect( +// 0, +// Math.floor(y + priorityHeight), +// canvasWidth, +// REACT_PRIORITY_BORDER_SIZE, +// ); + +// context.fillStyle = COLORS.PRIORITY_BORDER; +// context.fillRect( +// Math.floor(LABEL_FIXED_WIDTH) - REACT_PRIORITY_BORDER_SIZE, +// Math.floor(y), +// REACT_PRIORITY_BORDER_SIZE, +// priorityHeight, +// ); + +// context.fillStyle = COLORS.PRIORITY_LABEL; +// context.textAlign = 'left'; +// context.textBaseline = 'middle'; +// context.font = `${LABEL_FONT_SIZE}px sans-serif`; +// context.fillText(priority, 4, y + priorityHeight / 2); + +// y += priorityHeight + REACT_PRIORITY_BORDER_SIZE; +// }); +// } function renderAxisMarkers( context, @@ -472,13 +555,11 @@ function renderAxisMarkers( // TODO Passing "state" directly breaks memoization for e.g. mouse moves export const renderCanvas = memoize( ( - data: $ReadOnly, + data: $ReadOnly, flamechart: $ReadOnly, canvas: HTMLCanvasElement, canvasWidth: number, canvasHeight: number, - /** Precomputed height of marks and measures canvas section */ - schedulerCanvasHeight: number, // TODO: Figure out why this can't be calculated here state: $ReadOnly, hoveredEvent: $ReadOnly | null, ) => { @@ -488,7 +569,7 @@ export const renderCanvas = memoize( renderBackgroundFills(context, canvasWidth, canvasHeight); - renderReactMarksAndMeasures( + const schedulerAreaEndY = renderReactMarksAndMeasures( context, data, state, @@ -509,17 +590,17 @@ export const renderCanvas = memoize( hoveredEvent, canvasWidth, canvasHeight, - HEADER_HEIGHT_FIXED + schedulerCanvasHeight - offsetY, + HEADER_HEIGHT_FIXED + schedulerAreaEndY - offsetY, ); // LEFT: Priority labels // Render them last, on top of everything else, to account for things scrolled beneath them. - renderPriorityLabels( - context, - data, - canvasWidth, - HEADER_HEIGHT_FIXED - offsetY, - ); + // renderPriorityLabels( + // context, + // data, + // canvasWidth, + // HEADER_HEIGHT_FIXED - offsetY, + // ); // TOP: Time markers // Time markers do not scroll off screen; they are always rendered at a fixed vertical position. From 040856526fa71518ab5e09e2c4558663b55e850a Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Fri, 3 Jul 2020 10:38:11 +0800 Subject: [PATCH 030/116] [Canvas V2][2/n] Implement lane dividers and background (#32) --- src/canvas/renderCanvas.js | 78 ++++++++++++-------------------------- 1 file changed, 24 insertions(+), 54 deletions(-) diff --git a/src/canvas/renderCanvas.js b/src/canvas/renderCanvas.js index ef117f939e20f..6c9750ebd71c4 100644 --- a/src/canvas/renderCanvas.js +++ b/src/canvas/renderCanvas.js @@ -102,6 +102,20 @@ function renderReactMarksAndMeasures( let laneMinY = canvasStartY; + // Render lanes background. + // TODO: Figure out a way not to compute total height twice + const schedulerAreaHeight = lanesToRender.reduce( + (height, lane) => height + getLaneHeight(data, lane), + 0, + ); + context.fillStyle = COLORS.PRIORITY_BACKGROUND; + context.fillRect( + 0, + Math.floor(canvasStartY), + canvasWidth, + schedulerAreaHeight, + ); + lanesToRender.forEach(lane => { const baseY = laneMinY + REACT_GUTTER_SIZE; @@ -159,6 +173,15 @@ function renderReactMarksAndMeasures( }); laneMinY += getLaneHeight(data, lane); + + // Render bottom border + context.fillStyle = COLORS.PRIORITY_BORDER; + context.fillRect( + 0, + Math.floor(laneMinY - state.offsetY - REACT_PRIORITY_BORDER_SIZE), + canvasWidth, + REACT_PRIORITY_BORDER_SIZE, + ); }); return laneMinY; @@ -454,50 +477,6 @@ function renderFlamechart( } } -// function renderPriorityLabels(context, data, canvasWidth, canvasStartY) { -// let y = canvasStartY; - -// REACT_PRIORITIES.forEach((priority, priorityIndex) => { -// const priorityHeight = getPriorityHeight(data, priority); - -// if (priorityHeight === 0) { -// return; -// } - -// context.fillStyle = COLORS.PRIORITY_BACKGROUND; -// context.fillRect( -// 0, -// Math.floor(y), -// Math.floor(LABEL_FIXED_WIDTH), -// priorityHeight, -// ); - -// context.fillStyle = COLORS.PRIORITY_BORDER; -// context.fillRect( -// 0, -// Math.floor(y + priorityHeight), -// canvasWidth, -// REACT_PRIORITY_BORDER_SIZE, -// ); - -// context.fillStyle = COLORS.PRIORITY_BORDER; -// context.fillRect( -// Math.floor(LABEL_FIXED_WIDTH) - REACT_PRIORITY_BORDER_SIZE, -// Math.floor(y), -// REACT_PRIORITY_BORDER_SIZE, -// priorityHeight, -// ); - -// context.fillStyle = COLORS.PRIORITY_LABEL; -// context.textAlign = 'left'; -// context.textBaseline = 'middle'; -// context.font = `${LABEL_FONT_SIZE}px sans-serif`; -// context.fillText(priority, 4, y + priorityHeight / 2); - -// y += priorityHeight + REACT_PRIORITY_BORDER_SIZE; -// }); -// } - function renderAxisMarkers( context, state, @@ -590,18 +569,9 @@ export const renderCanvas = memoize( hoveredEvent, canvasWidth, canvasHeight, - HEADER_HEIGHT_FIXED + schedulerAreaEndY - offsetY, + schedulerAreaEndY - offsetY, ); - // LEFT: Priority labels - // Render them last, on top of everything else, to account for things scrolled beneath them. - // renderPriorityLabels( - // context, - // data, - // canvasWidth, - // HEADER_HEIGHT_FIXED - offsetY, - // ); - // TOP: Time markers // Time markers do not scroll off screen; they are always rendered at a fixed vertical position. // Render them last, on top of everything else, to account for things scrolled beneath them. From 92702a91ecd347ff6a3bea90c9a7625dad43fd4a Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Fri, 3 Jul 2020 10:42:41 +0800 Subject: [PATCH 031/116] [Canvas V2][3/n] Implement React event row (#33) --- src/canvas/constants.js | 3 +- src/canvas/renderCanvas.js | 334 ++++++++++++++++++------------------- 2 files changed, 160 insertions(+), 177 deletions(-) diff --git a/src/canvas/constants.js b/src/canvas/constants.js index 8dccfd0558e87..3674be87cb008 100644 --- a/src/canvas/constants.js +++ b/src/canvas/constants.js @@ -10,7 +10,7 @@ export const MARKER_TEXT_PADDING = 8; export const BAR_HEIGHT = 16; export const BAR_HORIZONTAL_SPACING = 1; export const BAR_SPACER_SIZE = 6; -export const EVENT_SIZE = 6; +export const EVENT_SIZE = 6; // TODO: What's the difference between this and REACT_EVENT_SIZE? export const MIN_BAR_WIDTH = 1; export const SECTION_GUTTER_SIZE = 4; @@ -45,6 +45,7 @@ export const FONT_SIZE = 10; export const BORDER_OPACITY = 0.4; export const REACT_GUTTER_SIZE = 0; +export const REACT_EVENT_ROW_PADDING = 4; export const REACT_EVENT_SIZE = 6; export const REACT_WORK_SIZE = 12; export const REACT_EVENT_BORDER_SIZE = 1; diff --git a/src/canvas/renderCanvas.js b/src/canvas/renderCanvas.js index 6c9750ebd71c4..48d39fc409187 100644 --- a/src/canvas/renderCanvas.js +++ b/src/canvas/renderCanvas.js @@ -37,6 +37,9 @@ import { FLAMECHART_TEXT_PADDING, LABEL_FIXED_WIDTH, HEADER_HEIGHT_FIXED, + REACT_EVENT_SIZE, + EVENT_SIZE, + REACT_EVENT_ROW_PADDING, } from './constants'; import {REACT_TOTAL_NUM_LANES} from '../constants'; @@ -75,6 +78,9 @@ import {REACT_TOTAL_NUM_LANES} from '../constants'; // '────────────────────────── // +// TODO: (windowing, optimization) We can avoid rendering offscreen data in many +// of the render* functions in this file. + function renderBackgroundFills(context, canvasWidth, canvasHeight) { // Fill the canvas with the background color context.fillStyle = COLORS.BACKGROUND; @@ -82,11 +88,141 @@ function renderBackgroundFills(context, canvasWidth, canvasHeight) { } /** - * Render all charting data (once it's loaded and processed) within the - * "scrollable" region. + * Render React events from `data` in a single row. + * + * The React events will be rendered into the canvas `context` of dimensions + * `canvasWidth`x`canvasHeight`, starting at `canvasStartY`. The events will be + * offset by pan and zoom `state`. Optionally with a highlighted + * `hoveredEvent`. + * + * @see renderSingleReactEvent */ -// TODO (windowing) We can avoid rendering all of this if we've scrolled some of it off screen. -function renderReactMarksAndMeasures( +function renderReactEventRow( + context, + events, + state, + hoveredEvent, + canvasWidth, + canvasHeight, + canvasStartY, +): number { + const {offsetY} = state; + + // Draw events + const baseY = canvasStartY + REACT_EVENT_ROW_PADDING; + events.forEach(event => { + const showHoverHighlight = hoveredEvent && hoveredEvent.event === event; + renderSingleReactEvent( + context, + state, + event, + canvasWidth, + baseY, + offsetY, + showHoverHighlight, + ); + }); + + // Draw the hovered and/or selected items on top so they stand out. + // This is helpful if there are multiple (overlapping) items close to each other. + if (hoveredEvent !== null && hoveredEvent.event !== null) { + renderSingleReactEvent( + context, + state, + hoveredEvent.event, + canvasWidth, + baseY, + offsetY, + true, + ); + } + + const rowHeight = + REACT_EVENT_ROW_PADDING + REACT_EVENT_SIZE + REACT_EVENT_ROW_PADDING; + + // Render bottom border + context.fillStyle = COLORS.PRIORITY_BORDER; + context.fillRect( + 0, + Math.floor(canvasStartY + rowHeight - offsetY - REACT_PRIORITY_BORDER_SIZE), + canvasWidth, + REACT_PRIORITY_BORDER_SIZE, + ); + + return canvasStartY + rowHeight; +} + +/** + * Render a single `ReactEvent` as a circle in the canvas. + * + * @see renderReactEventRow + */ +function renderSingleReactEvent( + context, + state, + event, + canvasWidth, + baseY, + panOffsetY, + showHoverHighlight, +) { + const {timestamp, type} = event; + + const x = timestampToPosition(timestamp, state); + if (x + EVENT_SIZE / 2 < 0 || canvasWidth < x) { + return; // Not in view + } + + let fillStyle = null; + + switch (type) { + case 'schedule-render': + case 'schedule-state-update': + case 'schedule-force-update': + if (event.isCascading) { + fillStyle = showHoverHighlight + ? COLORS.REACT_SCHEDULE_CASCADING_HOVER + : COLORS.REACT_SCHEDULE_CASCADING; + } else { + fillStyle = showHoverHighlight + ? COLORS.REACT_SCHEDULE_HOVER + : COLORS.REACT_SCHEDULE; + } + break; + case 'suspense-suspend': + case 'suspense-resolved': + case 'suspense-rejected': + fillStyle = showHoverHighlight + ? COLORS.REACT_SUSPEND_HOVER + : COLORS.REACT_SUSPEND; + break; + default: + console.warn(`Unexpected event type "${type}"`); + break; + } + + if (fillStyle !== null) { + const circumference = REACT_EVENT_SIZE; + const y = baseY + REACT_EVENT_SIZE / 2 - panOffsetY; + + context.beginPath(); + context.fillStyle = fillStyle; + context.arc(x, y, circumference / 2, 0, 2 * Math.PI); + context.fill(); + } +} + +/** + * Render React measures from `data` in parallel lanes. + * + * The React measures will be rendered into the canvas `context` of dimensions + * `canvasWidth`x`canvasHeight`, starting at `canvasStartY`. The measures will + * be offset by pan and zoom `state`. Optionally with a highlighted + * `hoveredEvent`. + * + * @see renderSingleReactMeasure + */ +function renderReactMeasures( context, data, state, @@ -95,6 +231,8 @@ function renderReactMarksAndMeasures( canvasHeight, canvasStartY, ): number { + const {offsetY} = state; + // TODO: Compute lanes to render from data? Or just use getLaneHeight to skip lanes const lanesToRender: ReactLane[] = Array.from( Array(REACT_TOTAL_NUM_LANES).keys(), @@ -111,7 +249,7 @@ function renderReactMarksAndMeasures( context.fillStyle = COLORS.PRIORITY_BACKGROUND; context.fillRect( 0, - Math.floor(canvasStartY), + Math.floor(canvasStartY - offsetY), canvasWidth, schedulerAreaHeight, ); @@ -119,38 +257,6 @@ function renderReactMarksAndMeasures( lanesToRender.forEach(lane => { const baseY = laneMinY + REACT_GUTTER_SIZE; - // TODO: Draw a separate event gutter. Split into a renderReactMarks function? - // if (data.events.length > 0) { - // data.events.forEach(event => { - // const showHoverHighlight = hoveredEvent && hoveredEvent.event === event; - // renderSingleReactMarkOrMeasure({ - // baseY, - // canvasWidth, - // context, - // eventOrMeasure: event, - // showGroupHighlight: false, - // showHoverHighlight, - // state, - // }); - // }); - - // // Draw the hovered and/or selected items on top so they stand out. - // // This is helpful if there are multiple (overlapping) items close to each other. - // // if (hoveredEvent !== null && hoveredEvent.event !== null) { - // // renderSingleReactMarkOrMeasure({ - // // baseY, - // // canvasWidth, - // // context, - // // eventOrMeasure: hoveredEvent.event, - // // showGroupHighlight: false, - // // showHoverHighlight: true, - // // state, - // // }); - // // } - - // baseY += REACT_EVENT_SIZE + REACT_GUTTER_SIZE; - // } - data.measures // TODO: Optimization: precompute this so that we don't filter this array |lanesToRender| times .filter(measure => measure.lanes.includes(lane)) @@ -178,7 +284,7 @@ function renderReactMarksAndMeasures( context.fillStyle = COLORS.PRIORITY_BORDER; context.fillRect( 0, - Math.floor(laneMinY - state.offsetY - REACT_PRIORITY_BORDER_SIZE), + Math.floor(laneMinY - offsetY - REACT_PRIORITY_BORDER_SIZE), canvasWidth, REACT_PRIORITY_BORDER_SIZE, ); @@ -269,142 +375,6 @@ function renderSingleReactMeasure( ); } -// function renderSingleReactMarkOrMeasure({ -// baseY, -// canvasWidth, -// context, -// eventOrMeasure, -// showGroupHighlight, -// showHoverHighlight, -// state, -// }) { -// const {timestamp, type} = eventOrMeasure; -// const {offsetY} = state; - -// let fillStyle = null; -// let hoveredFillStyle = null; -// let groupSelectedFillStyle = null; -// let x, y, width; - -// switch (type) { -// case 'commit': -// case 'render-idle': -// case 'render': -// case 'layout-effects': -// case 'passive-effects': -// const {depth, duration} = ((eventOrMeasure: any): ReactMeasure); - -// // We could change the max to 0 and just skip over rendering anything that small, -// // but this has the effect of making the chart look very empty when zoomed out. -// // So long as perf is okay- it might be best to err on the side of showing things. -// width = durationToWidth(duration, state); -// if (width <= 0) { -// return; // Too small to render at this zoom level -// } - -// x = timestampToPosition(timestamp, state); -// if (x + width < 0 || canvasWidth < x) { -// return; // Not in view -// } - -// switch (type) { -// case 'commit': -// fillStyle = COLORS.REACT_COMMIT; -// hoveredFillStyle = COLORS.REACT_COMMIT_HOVER; -// groupSelectedFillStyle = COLORS.REACT_COMMIT_SELECTED; -// break; -// case 'render-idle': -// // We could render idle time as diagonal hashes. -// // This looks nicer when zoomed in, but not so nice when zoomed out. -// // color = context.createPattern(getIdlePattern(), 'repeat'); -// fillStyle = COLORS.REACT_IDLE; -// hoveredFillStyle = COLORS.REACT_IDLE_HOVER; -// groupSelectedFillStyle = COLORS.REACT_IDLE_SELECTED; -// break; -// case 'render': -// fillStyle = COLORS.REACT_RENDER; -// hoveredFillStyle = COLORS.REACT_RENDER_HOVER; -// groupSelectedFillStyle = COLORS.REACT_RENDER_SELECTED; -// break; -// case 'layout-effects': -// fillStyle = COLORS.REACT_LAYOUT_EFFECTS; -// hoveredFillStyle = COLORS.REACT_LAYOUT_EFFECTS_HOVER; -// groupSelectedFillStyle = COLORS.REACT_LAYOUT_EFFECTS_SELECTED; -// break; -// case 'passive-effects': -// fillStyle = COLORS.REACT_PASSIVE_EFFECTS; -// hoveredFillStyle = COLORS.REACT_PASSIVE_EFFECTS_HOVER; -// groupSelectedFillStyle = COLORS.REACT_PASSIVE_EFFECTS_SELECTED; -// break; -// default: -// console.warn(`Unexpected type "${type}"`); -// break; -// } - -// y = baseY + REACT_WORK_SIZE * depth + REACT_GUTTER_SIZE * depth - offsetY; - -// // $FlowFixMe We know these won't be null -// context.fillStyle = showHoverHighlight -// ? hoveredFillStyle -// : showGroupHighlight -// ? groupSelectedFillStyle -// : fillStyle; -// context.fillRect( -// Math.floor(x), -// Math.floor(y), -// Math.floor(width), -// REACT_WORK_SIZE, -// ); -// break; -// case 'schedule-render': -// case 'schedule-state-update': -// case 'suspend': -// const {isCascading} = ((eventOrMeasure: any): ReactEvent); - -// x = timestampToPosition(timestamp, state); -// if (x + EVENT_SIZE / 2 < 0 || canvasWidth < x) { -// return; // Not in view -// } - -// switch (type) { -// case 'schedule-render': -// case 'schedule-state-update': -// if (isCascading) { -// fillStyle = showHoverHighlight -// ? COLORS.REACT_SCHEDULE_CASCADING_HOVER -// : COLORS.REACT_SCHEDULE_CASCADING; -// } else { -// fillStyle = showHoverHighlight -// ? COLORS.REACT_SCHEDULE_HOVER -// : COLORS.REACT_SCHEDULE; -// } -// break; -// case 'suspend': -// fillStyle = showHoverHighlight -// ? COLORS.REACT_SUSPEND_HOVER -// : COLORS.REACT_SUSPEND; -// break; -// default: -// console.warn(`Unexpected event or measure type "${type}"`); -// break; -// } - -// if (fillStyle !== null) { -// const circumference = REACT_EVENT_SIZE; -// y = baseY + REACT_EVENT_SIZE / 2 - offsetY; - -// context.beginPath(); -// context.fillStyle = fillStyle; -// context.arc(x, y, circumference / 2, 0, 2 * Math.PI); -// context.fill(); -// } -// break; -// default: -// console.warn(`Unexpected event or measure type "${type}"`); -// break; -// } -// } - function renderFlamechart( context, flamechart, @@ -548,7 +518,19 @@ export const renderCanvas = memoize( renderBackgroundFills(context, canvasWidth, canvasHeight); - const schedulerAreaEndY = renderReactMarksAndMeasures( + let schedulerAreaEndY = HEADER_HEIGHT_FIXED; + + schedulerAreaEndY = renderReactEventRow( + context, + data.events, + state, + hoveredEvent, + canvasWidth, + canvasHeight, + schedulerAreaEndY, + ); + + schedulerAreaEndY = renderReactMeasures( context, data, state, @@ -557,7 +539,7 @@ export const renderCanvas = memoize( canvasHeight, // Time markers do not scroll off screen; they are always rendered at a // fixed vertical position. - HEADER_HEIGHT_FIXED, + schedulerAreaEndY, ); // Flame graph data renders below the prioritized React data. From c3eb419152c8d599cf53ec3c638d7e85d523a088 Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Fri, 3 Jul 2020 10:51:31 +0800 Subject: [PATCH 032/116] [Canvas V2][4/n] Migrate hover and context menus (#34) --- src/App.js | 30 ++++---- src/CanvasPage.js | 25 +++---- src/EventTooltip.js | 39 ++++++----- src/canvas/canvasUtils.js | 140 +++++++++++++++++++------------------ src/canvas/constants.js | 2 + src/canvas/renderCanvas.js | 13 ++-- src/types.js | 12 ++-- src/util/getBatchRange.js | 12 +--- 8 files changed, 138 insertions(+), 135 deletions(-) diff --git a/src/App.js b/src/App.js index 6ad892d4f9728..6c65cde7eed28 100644 --- a/src/App.js +++ b/src/App.js @@ -2,6 +2,7 @@ import type { FlamechartData, + ReactLane, ReactProfilerData, ReactProfilerDataV2, } from './types'; @@ -9,8 +10,8 @@ import type { import React, {useState, useCallback} from 'react'; import {unstable_batchedUpdates} from 'react-dom'; -import {getPriorityHeight} from './canvas/canvasUtils'; -import {REACT_PRIORITIES} from './canvas/constants'; +import {getLaneHeight} from './canvas/canvasUtils'; +import {REACT_TOTAL_NUM_LANES} from './constants'; import ImportPage from './ImportPage'; import CanvasPage from './CanvasPage'; @@ -26,19 +27,8 @@ export default function App() { const [schedulerCanvasHeight, setSchedulerCanvasHeight] = useState(0); const handleDataImported = useCallback( - ( - importedProfilerData: ReactProfilerData, - importedFlamechart: FlamechartData, - ) => { - unstable_batchedUpdates(() => { - setSchedulerCanvasHeight( - REACT_PRIORITIES.reduce((height, priority) => { - return height + getPriorityHeight(importedProfilerData, priority); - }, 0), - ); - setProfilerData(importedProfilerData); - setFlamechart(importedFlamechart); - }); + (importedProfilerData: ReactProfilerData) => { + setProfilerData(importedProfilerData); }, ); @@ -51,6 +41,16 @@ export default function App() { unstable_batchedUpdates(() => { setProfilerDataV2(importedProfilerData); setFlamechart(importedFlamechart); + + const lanesToRender: ReactLane[] = Array.from( + Array(REACT_TOTAL_NUM_LANES).keys(), + ); + // TODO: Figure out if this is necessary + setSchedulerCanvasHeight( + lanesToRender.reduce((height, lane) => { + return height + getLaneHeight(importedProfilerData, lane); + }, 0), + ); }); }, ); diff --git a/src/CanvasPage.js b/src/CanvasPage.js index f91345dfc5f2a..552c7a211be47 100644 --- a/src/CanvasPage.js +++ b/src/CanvasPage.js @@ -28,13 +28,12 @@ const CONTEXT_MENU_ID = 'canvas'; import type { FlamechartData, ReactHoverContextInfo, - ReactMeasure, ReactProfilerData, ReactProfilerDataV2, } from './types'; type ContextMenuContextData = {| - data: ReactProfilerData, + data: ReactProfilerDataV2, flamechart: FlamechartData, hoveredEvent: ReactHoverContextInfo | null, state: PanAndZoomState, @@ -73,10 +72,10 @@ function CanvasPage({ ); } -const copySummary = (data: ReactProfilerData, measure: ReactMeasure) => { - const {batchUID, duration, priority, timestamp, type} = measure; +const copySummary = (data, measure) => { + const {batchUID, duration, timestamp, type} = measure; - const [startTime, stopTime] = getBatchRange(batchUID, priority, data); + const [startTime, stopTime] = getBatchRange(batchUID, data); copy( JSON.stringify({ @@ -88,17 +87,13 @@ const copySummary = (data: ReactProfilerData, measure: ReactMeasure) => { ); }; -const zoomToBatch = ( - data: ReactProfilerData, - measure: ReactMeasure, - state: PanAndZoomState, -) => { +const zoomToBatch = (data, measure, state) => { const {zoomTo} = state; if (!zoomTo) { return; } - const {batchUID, priority} = measure; - const [startTime, stopTime] = getBatchRange(batchUID, priority, data); + const {batchUID} = measure; + const [startTime, stopTime] = getBatchRange(batchUID, data); zoomTo(startTime, stopTime); }; @@ -135,7 +130,7 @@ function AutoSizedCanvas({ const hoveredEvent = getHoveredEvent( schedulerCanvasHeight, - data, + dataV2, flamechart, state, ); @@ -143,7 +138,7 @@ function AutoSizedCanvas({ useContextMenu({ data: { - data, + data: dataV2, flamechart, hoveredEvent, state, @@ -229,7 +224,7 @@ function AutoSizedCanvas({ }} {!isContextMenuShown && ( - + )} ); diff --git a/src/EventTooltip.js b/src/EventTooltip.js index 3c7415b4b8c22..fd3faecf8a7bb 100644 --- a/src/EventTooltip.js +++ b/src/EventTooltip.js @@ -3,9 +3,9 @@ import type {PanAndZoomState} from './util/usePanAndZoom'; import type {FlamechartFrame} from './speedscope/lib/flamechart'; import type { - ReactEvent, - ReactMeasure, - ReactProfilerData, + ReactEventV2, + ReactMeasureV2, + ReactProfilerDataV2, ReactHoverContextInfo, Return, } from './types'; @@ -18,7 +18,7 @@ import useSmartTooltip from './util/useSmartTooltip'; import styles from './EventTooltip.css'; type Props = {| - data: ReactProfilerData, + data: ReactProfilerDataV2, hoveredEvent: ReactHoverContextInfo | null, state: PanAndZoomState, |}; @@ -49,6 +49,7 @@ export default function EventTooltip({data, hoveredEvent, state}: Props) { /> ); case 'schedule-state-update': // eslint-disable-line no-case-declarations + case 'schedule-force-update': const color = event.isCascading ? COLORS.REACT_SCHEDULE_CASCADING_HOVER : COLORS.REACT_SCHEDULE_HOVER; @@ -60,7 +61,9 @@ export default function EventTooltip({data, hoveredEvent, state}: Props) { tooltipRef={tooltipRef} /> ); - case 'suspend': + case 'suspense-suspend': + case 'suspense-resolved': + case 'suspense-rejected': return ( @@ -114,11 +116,9 @@ function formatComponentStack(componentStack: string): string { } const TooltipFlamechartNode = ({ - data, flamechartNode, tooltipRef, }: { - data: ReactProfilerData, flamechartNode: FlamechartFrame, tooltipRef: Return, }) => { @@ -144,13 +144,11 @@ const TooltipFlamechartNode = ({ const TooltipReactEvent = ({ color, - data, event, tooltipRef, }: { color: string, - data: ReactProfilerData, - event: ReactEvent, + event: ReactEventV2, tooltipRef: Return, }) => { const {componentName, componentStack, timestamp, type} = event; @@ -163,9 +161,18 @@ const TooltipReactEvent = ({ case 'schedule-state-update': label = 'state update scheduled'; break; - case 'suspend': + case 'schedule-force-update': + label = 'force update scheduled'; + break; + case 'suspense-suspend': label = 'suspended'; break; + case 'suspense-resolved': + label = 'suspense resolved'; + break; + case 'suspense-rejected': + label = 'suspense rejected'; + break; default: break; } @@ -206,11 +213,11 @@ const TooltipReactMeasure = ({ measure, tooltipRef, }: { - data: ReactProfilerData, - measure: ReactMeasure, + data: ReactProfilerDataV2, + measure: ReactMeasureV2, tooltipRef: Return, }) => { - const {batchUID, duration, priority, timestamp, type} = measure; + const {batchUID, duration, timestamp, type} = measure; let label = null; switch (type) { @@ -233,7 +240,7 @@ const TooltipReactMeasure = ({ break; } - const [startTime, stopTime] = getBatchRange(batchUID, priority, data); + const [startTime, stopTime] = getBatchRange(batchUID, data); return (
, + data: $ReadOnly, flamechart: $ReadOnly, state: PanAndZoomState, ): ReactHoverContextInfo | null { const {canvasMouseX, canvasMouseY, offsetY} = state; - if (canvasMouseX < LABEL_FIXED_WIDTH || canvasMouseY < HEADER_HEIGHT_FIXED) { + if (canvasMouseY < HEADER_HEIGHT_FIXED) { return null; } - if (canvasMouseY + offsetY < schedulerCanvasHeight) { - const adjustedCanvasMouseY = canvasMouseY - HEADER_HEIGHT_FIXED + offsetY; - let priorityMinY = HEADER_HEIGHT_FIXED; - let priorityIndex = null; - let priority: ReactPriority = 'unscheduled'; - for (let index = 0; index < REACT_PRIORITIES.length; index++) { - priority = REACT_PRIORITIES[index]; + if (canvasMouseY + offsetY < HEADER_HEIGHT_FIXED + EVENT_ROW_HEIGHT_FIXED) { + // Find hovered React event + + const {events} = data; + + // Because data ranges may overlap, we want to find the last intersecting item. + // This will always be the one on "top" (the one the user is hovering over). + for (let index = events.length - 1; index >= 0; index--) { + const event = events[index]; + const {timestamp} = event; + + const eventX = timestampToPosition(timestamp, state); + const startX = eventX - REACT_EVENT_SIZE / 2; + const stopX = eventX + REACT_EVENT_SIZE / 2; + if (canvasMouseX >= startX && canvasMouseX <= stopX) { + return { + event, + flamechartNode: null, + measure: null, + lane: null, + data, + }; + } + } + } else if ( + canvasMouseY + offsetY < + HEADER_HEIGHT_FIXED + EVENT_ROW_HEIGHT_FIXED + schedulerCanvasHeight + ) { + // Find hovered React measure - const priorityHeight = getPriorityHeight(data, priority); + const adjustedCanvasMouseY = canvasMouseY - HEADER_HEIGHT_FIXED + offsetY; + let laneMinY = EVENT_ROW_HEIGHT_FIXED; + let lane = null; + for ( + let laneIndex: ReactLane = 0; + laneIndex < REACT_TOTAL_NUM_LANES; + laneIndex++ + ) { + const laneHeight = getLaneHeight(data, laneIndex); if ( - adjustedCanvasMouseY >= priorityMinY && - adjustedCanvasMouseY <= priorityMinY + priorityHeight + adjustedCanvasMouseY >= laneMinY && + adjustedCanvasMouseY <= laneMinY + laneHeight ) { - priorityIndex = index; + lane = laneIndex; break; } - priorityMinY += priorityHeight; + laneMinY += laneHeight; } - if (priorityIndex === null) { + if (lane === null) { return null; } - const baseY = priorityMinY - offsetY; - const eventMinY = baseY + REACT_GUTTER_SIZE / 2; - const eventMaxY = eventMinY + REACT_EVENT_SIZE + REACT_GUTTER_SIZE; - const measureMinY = eventMaxY; - const measureMaxY = measureMinY + REACT_WORK_SIZE + REACT_GUTTER_SIZE; - - let events = null; - let measures = null; - if (canvasMouseY >= eventMinY && canvasMouseY <= eventMaxY) { - events = data[priority].events; - } else if (canvasMouseY >= measureMinY && canvasMouseY <= measureMaxY) { - measures = data[priority].measures; - } - - if (events !== null) { - for (let index = events.length - 1; index >= 0; index--) { - const event = events[index]; - const {timestamp} = event; - - const eventX = timestampToPosition(timestamp, state); - const startX = eventX - REACT_EVENT_SIZE / 2; - const stopX = eventX + REACT_EVENT_SIZE / 2; - if (canvasMouseX >= startX && canvasMouseX <= stopX) { - return { - event, - flamechartNode: null, - measure: null, - priorityIndex, - data, - }; - } + // Because data ranges may overlap, we want to find the last intersecting item. + // This will always be the one on "top" (the one the user is hovering over). + const {measures} = data; + for (let index = measures.length - 1; index >= 0; index--) { + const measure = measures[index]; + if (!measure.lanes.includes(lane)) { + continue; } - } else if (measures !== null) { - // Because data ranges may overlap, we want to find the last intersecting item. - // This will always be the one on "top" (the one the user is hovering over). - for (let index = measures.length - 1; index >= 0; index--) { - const measure = measures[index]; - const {duration, timestamp} = measure; - const pointerTime = positionToTimestamp(canvasMouseX, state); - - if (pointerTime >= timestamp && pointerTime <= timestamp + duration) { - return { - event: null, - flamechartNode: null, - measure, - priorityIndex, - data, - }; - } + const {duration, timestamp} = measure; + const pointerTime = positionToTimestamp(canvasMouseX, state); + + if (pointerTime >= timestamp && pointerTime <= timestamp + duration) { + return { + event: null, + flamechartNode: null, + measure, + lane, + data, + }; } } } else { + // Find hovered flamechart event + const layerIndex = Math.floor( - (canvasMouseY + offsetY - HEADER_HEIGHT_FIXED - schedulerCanvasHeight) / + (canvasMouseY + + offsetY - + HEADER_HEIGHT_FIXED - + EVENT_ROW_HEIGHT_FIXED - + schedulerCanvasHeight) / FLAMECHART_FRAME_HEIGHT, ); const layer = flamechart.layers[layerIndex]; @@ -221,7 +227,7 @@ export function getHoveredEvent( event: null, flamechartNode, measure: null, - priorityIndex: null, + lane: null, data, }; } diff --git a/src/canvas/constants.js b/src/canvas/constants.js index 3674be87cb008..403b2d054e6e3 100644 --- a/src/canvas/constants.js +++ b/src/canvas/constants.js @@ -57,6 +57,8 @@ export const FLAMECHART_TEXT_PADDING = 3; export const LABEL_FIXED_WIDTH = LABEL_SIZE + REACT_PRIORITY_BORDER_SIZE; export const HEADER_HEIGHT_FIXED = MARKER_HEIGHT + REACT_PRIORITY_BORDER_SIZE; +export const EVENT_ROW_HEIGHT_FIXED = + REACT_EVENT_ROW_PADDING + REACT_EVENT_SIZE + REACT_EVENT_ROW_PADDING; export const COLORS = Object.freeze({ BACKGROUND: '#ffffff', diff --git a/src/canvas/renderCanvas.js b/src/canvas/renderCanvas.js index 48d39fc409187..535a92775c07f 100644 --- a/src/canvas/renderCanvas.js +++ b/src/canvas/renderCanvas.js @@ -40,6 +40,7 @@ import { REACT_EVENT_SIZE, EVENT_SIZE, REACT_EVENT_ROW_PADDING, + EVENT_ROW_HEIGHT_FIXED, } from './constants'; import {REACT_TOTAL_NUM_LANES} from '../constants'; @@ -137,19 +138,21 @@ function renderReactEventRow( ); } - const rowHeight = - REACT_EVENT_ROW_PADDING + REACT_EVENT_SIZE + REACT_EVENT_ROW_PADDING; - // Render bottom border context.fillStyle = COLORS.PRIORITY_BORDER; context.fillRect( 0, - Math.floor(canvasStartY + rowHeight - offsetY - REACT_PRIORITY_BORDER_SIZE), + Math.floor( + canvasStartY + + EVENT_ROW_HEIGHT_FIXED - + offsetY - + REACT_PRIORITY_BORDER_SIZE, + ), canvasWidth, REACT_PRIORITY_BORDER_SIZE, ); - return canvasStartY + rowHeight; + return canvasStartY + EVENT_ROW_HEIGHT_FIXED; } /** diff --git a/src/types.js b/src/types.js index ea2e255ab101a..f9a8545dce002 100644 --- a/src/types.js +++ b/src/types.js @@ -72,14 +72,10 @@ export type ReactProfilerData = {| |}; export type ReactHoverContextInfo = {| - /** @deprecated */ - event: ReactEvent | null, - /** @deprecated */ - measure: ReactMeasure | null, - /** @deprecated */ - priorityIndex: number | null, - /** @deprecated */ - data: $ReadOnly | null, + event: ReactEventV2 | null, + measure: ReactMeasureV2 | null, + lane: ReactLane | null, + data: $ReadOnly | null, flamechartNode: FlamechartFrame | null, |}; diff --git a/src/util/getBatchRange.js b/src/util/getBatchRange.js index d17add4950ed2..393766940002c 100644 --- a/src/util/getBatchRange.js +++ b/src/util/getBatchRange.js @@ -2,22 +2,16 @@ import memoize from 'memoize-one'; -import type { - BatchUID, - Milliseconds, - ReactPriority, - ReactProfilerData, -} from './types'; +import type {BatchUID, Milliseconds, ReactProfilerDataV2} from '../types'; // TODO Batch duration probably shouldn't include delayed passive effects? // It should probably end with the layout effect. function unmemoizedGetBatchRange( batchUID: BatchUID, - priority: ReactPriority, - data: ReactProfilerData, + data: ReactProfilerDataV2, ): [Milliseconds, Milliseconds] { - const {measures} = data[priority]; + const {measures} = data; let startTime = 0; let stopTime = Infinity; From a73c9c4e0df9688b3b05f086ca2c27d68d4b0548 Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Fri, 3 Jul 2020 11:46:42 +0800 Subject: [PATCH 033/116] Remove V1 types and usage --- src/App.js | 27 +-- src/CanvasPage.js | 6 - src/ImportPage.js | 31 +--- src/canvas/canvasUtils.js | 42 ----- src/types.js | 88 +++------- src/util/preprocessData.js | 338 ------------------------------------- 6 files changed, 26 insertions(+), 506 deletions(-) delete mode 100644 src/util/preprocessData.js diff --git a/src/App.js b/src/App.js index 6c65cde7eed28..c8b2bf0d0e710 100644 --- a/src/App.js +++ b/src/App.js @@ -1,11 +1,6 @@ // @flow -import type { - FlamechartData, - ReactLane, - ReactProfilerData, - ReactProfilerDataV2, -} from './types'; +import type {FlamechartData, ReactLane, ReactProfilerDataV2} from './types'; import React, {useState, useCallback} from 'react'; import {unstable_batchedUpdates} from 'react-dom'; @@ -16,9 +11,6 @@ import ImportPage from './ImportPage'; import CanvasPage from './CanvasPage'; export default function App() { - const [profilerData, setProfilerData] = useState( - null, - ); const [ profilerDataV2, setProfilerDataV2, @@ -26,13 +18,6 @@ export default function App() { const [flamechart, setFlamechart] = useState(null); const [schedulerCanvasHeight, setSchedulerCanvasHeight] = useState(0); - const handleDataImported = useCallback( - (importedProfilerData: ReactProfilerData) => { - setProfilerData(importedProfilerData); - }, - ); - - // TODO: Migrate and completely remove V2 stuff const handleDataImportedV2 = useCallback( ( importedProfilerData: ReactProfilerDataV2, @@ -55,21 +40,15 @@ export default function App() { }, ); - if (profilerData && profilerDataV2 && flamechart) { + if (profilerDataV2 && flamechart) { return ( ); } else { - return ( - - ); + return ; } } diff --git a/src/CanvasPage.js b/src/CanvasPage.js index 552c7a211be47..c117e4d47a4e7 100644 --- a/src/CanvasPage.js +++ b/src/CanvasPage.js @@ -28,7 +28,6 @@ const CONTEXT_MENU_ID = 'canvas'; import type { FlamechartData, ReactHoverContextInfo, - ReactProfilerData, ReactProfilerDataV2, } from './types'; @@ -40,14 +39,12 @@ type ContextMenuContextData = {| |}; type Props = {| - profilerData: ReactProfilerData, profilerDataV2: ReactProfilerDataV2, flamechart: FlamechartData, schedulerCanvasHeight: number, |}; function CanvasPage({ - profilerData, profilerDataV2, flamechart, schedulerCanvasHeight, @@ -59,7 +56,6 @@ function CanvasPage({ {({height, width}: {height: number, width: number}) => ( { }; type AutoSizedCanvasProps = {| - data: ReactProfilerData, dataV2: ReactProfilerDataV2, flamechart: FlamechartData, height: number, @@ -107,7 +102,6 @@ type AutoSizedCanvasProps = {| |}; function AutoSizedCanvas({ - data, dataV2, flamechart, height, diff --git a/src/ImportPage.js b/src/ImportPage.js index 47b9c9d971a6c..2e2e2b162d028 100644 --- a/src/ImportPage.js +++ b/src/ImportPage.js @@ -1,51 +1,24 @@ // @flow import type {TimelineEvent} from './speedscope/import/chrome'; -import type { - FlamechartData, - ReactProfilerData, - ReactProfilerDataV2, -} from './types'; +import type {FlamechartData, ReactProfilerDataV2} from './types'; import React, {useEffect} from 'react'; -import preprocessData from './util/preprocessData'; import preprocessDataV2 from './util/preprocessDataV2'; import preprocessFlamechart from './util/preprocessFlamechart'; // TODO: Add import button but keep a static path until canvas layout is ready -import JSON_PATH from 'url:../static/small-devtools.json'; import JSON_PATHV2 from 'url:../static/Profile-20200625T133129.json'; type Props = {| - onDataImported: ( - profilerData: ReactProfilerData, - flamechart: FlamechartData, - ) => void, onDataImportedV2: ( profilerData: ReactProfilerDataV2, flamechart: FlamechartData, ) => void, |}; -export default function ImportPage({onDataImported, onDataImportedV2}: Props) { - useEffect(() => { - fetch(JSON_PATH) - .then(res => res.json()) - .then((events: TimelineEvent[]) => { - // Filter null entries and sort by timestamp. - // I would not expect to have to do either of this, - // but some of the data being passed in requires it. - events = events.filter(Boolean).sort((a, b) => (a.ts > b.ts ? 1 : -1)); - - if (events.length > 0) { - const processedData = preprocessData(events); - const processedFlamechart = preprocessFlamechart(events); - onDataImported(processedData, processedFlamechart); - } - }); - }, []); - +export default function ImportPage({onDataImportedV2}: Props) { useEffect(() => { fetch(JSON_PATHV2) .then(res => res.json()) diff --git a/src/canvas/canvasUtils.js b/src/canvas/canvasUtils.js index 65ba867e1e523..babdd23bcfa95 100644 --- a/src/canvas/canvasUtils.js +++ b/src/canvas/canvasUtils.js @@ -5,8 +5,6 @@ import type { FlamechartData, ReactHoverContextInfo, ReactLane, - ReactPriority, - ReactProfilerData, ReactProfilerDataV2, } from '../types'; import type {PanAndZoomState} from '../util/usePanAndZoom'; @@ -244,46 +242,6 @@ export function getHoveredEvent( return null; } -const cachedPriorityHeights = new Map(); -export const getPriorityHeight = ( - data: $ReadOnly, - priority: ReactPriority, -): number => { - if (cachedPriorityHeights.has(priority)) { - // We know the value must be present because we've just checked. - return ((cachedPriorityHeights.get(priority): any): number); - } else { - const numMeasures = data[priority].maxNestedMeasures; - const events = data[priority].events; - - let priorityHeight = 0; - if (numMeasures > 0 && events.length > 0) { - priorityHeight = - REACT_GUTTER_SIZE + - REACT_EVENT_SIZE + - REACT_WORK_SIZE * numMeasures + - REACT_GUTTER_SIZE * numMeasures + - REACT_PRIORITY_BORDER_SIZE; - } else if (numMeasures > 0) { - priorityHeight = - REACT_GUTTER_SIZE + - REACT_WORK_SIZE * numMeasures + - REACT_GUTTER_SIZE * numMeasures + - REACT_PRIORITY_BORDER_SIZE; - } else if (events.length > 0) { - priorityHeight = - REACT_GUTTER_SIZE + - REACT_EVENT_SIZE + - REACT_GUTTER_SIZE + - REACT_PRIORITY_BORDER_SIZE; - } - - cachedPriorityHeights.set(priority, priorityHeight); - - return priorityHeight; - } -}; - export const getLaneHeight = ( data: $ReadOnly, lane: ReactLane, diff --git a/src/types.js b/src/types.js index f9a8545dce002..557bfa369425f 100644 --- a/src/types.js +++ b/src/types.js @@ -14,73 +14,6 @@ export type Return = Return_<*, T>; export type Milliseconds = number; -/** @deprecated */ -export type ReactPriority = 'unscheduled' | 'high' | 'normal' | 'low'; - -/** @deprecated */ -export type ReactEventType = - | 'schedule-render' - | 'schedule-state-update' - | 'suspend'; - -export type ReactMeasureType = - | 'commit' - // render-idle: A measure spanning the time when a render starts, through all - // yields and restarts, and ends when commit stops OR render is cancelled. - | 'render-idle' - | 'render' - | 'layout-effects' - | 'passive-effects'; - -/** @deprecated */ -export type ReactEvent = {| - +type: ReactEventType, - +priority: ReactPriority, - +timestamp: Milliseconds, - +componentName?: string, - +componentStack?: string, - +isCascading?: boolean, -|}; - -export type BatchUID = number; - -/** @deprecated */ -export type ReactMeasure = {| - +type: ReactMeasureType, - +priority: ReactPriority, - +timestamp: Milliseconds, - +duration: Milliseconds, - +batchUID: BatchUID, - +depth: number, -|}; - -/** @deprecated */ -export type ReactProfilerDataPriority = {| - events: Array, - measures: Array, - maxNestedMeasures: number, -|}; - -/** @deprecated */ -export type ReactProfilerData = {| - startTime: number, - duration: number, - unscheduled: ReactProfilerDataPriority, - high: ReactProfilerDataPriority, - normal: ReactProfilerDataPriority, - low: ReactProfilerDataPriority, -|}; - -export type ReactHoverContextInfo = {| - event: ReactEventV2 | null, - measure: ReactMeasureV2 | null, - lane: ReactLane | null, - data: $ReadOnly | null, - flamechartNode: FlamechartFrame | null, -|}; - -export type FlamechartData = Flamechart; - export type ReactLane = number; type BaseReactEvent = {| @@ -134,6 +67,17 @@ export type ReactEventV2 = | ReactSuspenseRejectedEvent; export type ReactEventTypeV2 = $PropertyType; +export type ReactMeasureType = + | 'commit' + // render-idle: A measure spanning the time when a render starts, through all + // yields and restarts, and ends when commit stops OR render is cancelled. + | 'render-idle' + | 'render' + | 'layout-effects' + | 'passive-effects'; + +export type BatchUID = number; + export type ReactMeasureV2 = {| +type: ReactMeasureType, +lanes: ReactLane[], @@ -149,3 +93,13 @@ export type ReactProfilerDataV2 = {| events: ReactEventV2[], measures: ReactMeasureV2[], |}; + +export type ReactHoverContextInfo = {| + event: ReactEventV2 | null, + measure: ReactMeasureV2 | null, + lane: ReactLane | null, + data: $ReadOnly | null, + flamechartNode: FlamechartFrame | null, +|}; + +export type FlamechartData = Flamechart; diff --git a/src/util/preprocessData.js b/src/util/preprocessData.js deleted file mode 100644 index fda39690decb5..0000000000000 --- a/src/util/preprocessData.js +++ /dev/null @@ -1,338 +0,0 @@ -// @flow - -import type {TimelineEvent} from './speedscope/import/chrome'; - -import type { - Milliseconds, - BatchUID, - ReactEvent, - ReactMeasureType, - ReactPriority, - ReactProfilerData, - ReactProfilerDataPriority, -} from './types'; - -// TODO Combine yields/starts that are closer than some threshold with the previous event to reduce renders. - -// TODO: Figure out what this is -type StackElement = {| - type: ReactMeasureType, - depth: number, - index: number, - startTime: Milliseconds, - stopTime?: Milliseconds, -|}; - -type Metadata = {| - nextRenderShouldGenerateNewBatchID: boolean, - batchUID: BatchUID, - +stack: StackElement[], -|}; - -export default function reactProfilerProcessor( - rawData: TimelineEvent[], -): ReactProfilerData { - const reactProfilerData = { - startTime: rawData[0].ts, - duration: 0, - high: { - events: [], - measures: [], - maxNestedMeasures: 0, - }, - normal: { - events: [], - measures: [], - maxNestedMeasures: 0, - }, - low: { - events: [], - measures: [], - maxNestedMeasures: 0, - }, - unscheduled: { - events: [], - measures: [], - maxNestedMeasures: 0, - }, - }; - - let currentMetadata: Metadata | null = null; - let currentPriority: ReactPriority = 'unscheduled'; - let currentProfilerDataGroup: ReactProfilerDataPriority | null = null; - let uidCounter = 0; - - const metadata: {|[priority: ReactPriority]: Metadata|} = { - high: { - batchUID: 0, - nextRenderShouldGenerateNewBatchID: true, - stack: [], - }, - normal: { - batchUID: 0, - nextRenderShouldGenerateNewBatchID: true, - stack: [], - }, - low: { - batchUID: 0, - nextRenderShouldGenerateNewBatchID: true, - stack: [], - }, - unscheduled: { - batchUID: 0, - nextRenderShouldGenerateNewBatchID: true, - stack: [], - }, - }; - - const getLastType = () => { - if (!currentMetadata) { - return null; - } - const {stack} = currentMetadata; - if (stack.length > 0) { - const {type} = stack[stack.length - 1]; - return type; - } - return null; - }; - - const getDepth = () => { - if (!currentMetadata) { - return 0; - } - const {stack} = currentMetadata; - if (stack.length > 0) { - const {depth, type} = (stack[stack.length - 1]: StackElement); - return type === 'render-idle' ? depth : depth + 1; - } - return 0; - }; - - const markWorkCompleted = ( - type: ReactMeasureType, - stopTime: Milliseconds, - ) => { - if (!currentMetadata) { - return; - } - const {stack} = currentMetadata; - if (stack.length === 0) { - console.error( - `Unexpected type "${type}" completed while stack is empty.`, - ); - } else { - const last = stack[stack.length - 1]; - if (last.type !== type) { - console.error( - `Unexpected type "${type}" completed before "${last.type}" completed.`, - ); - } else { - const {index, startTime} = stack.pop(); - - if (currentProfilerDataGroup) { - const measure = currentProfilerDataGroup.measures[index]; - if (!measure) { - console.error( - `Could not find matching measure for type "${type}".`, - ); - } else { - // $FlowFixMe This property should not be writable outside of this function. - measure.duration = stopTime - startTime; - } - } - } - } - }; - - const markWorkStarted = (type: ReactMeasureType, startTime: Milliseconds) => { - if (!currentMetadata || !currentProfilerDataGroup) { - return; - } - const {batchUID, stack} = currentMetadata; - - const index = currentProfilerDataGroup.measures.length; - const depth = getDepth(); - - currentProfilerDataGroup.maxNestedMeasures = Math.max( - currentProfilerDataGroup.maxNestedMeasures, - depth + 1, - ); - - stack.push({ - depth, - index, - startTime, - type, - }); - - currentProfilerDataGroup.measures.push({ - type, - batchUID, - depth, - priority: currentPriority, - timestamp: startTime, - duration: 0, - }); - }; - - const throwIfIncomplete = type => { - if (!currentMetadata) { - return; - } - const {stack} = currentMetadata; - const lastIndex = stack.length - 1; - if (lastIndex >= 0) { - const last = stack[lastIndex]; - if (last.stopTime === undefined && last.type === type) { - throw new Error( - `Unexpected type "${type}" started before "${last.type}" completed.`, - ); - } - } - }; - - for (let i = 0; i < rawData.length; i++) { - const currentEvent = rawData[i]; - - const {cat, name, ts} = currentEvent; - - if (cat !== 'blink.user_timing' || !name.startsWith('--')) { - continue; - } - - currentMetadata = metadata[currentPriority] || metadata.unscheduled; - if (!currentMetadata) { - console.error('Unexpected priority', currentPriority); - } - - currentProfilerDataGroup = - reactProfilerData[currentPriority || 'unscheduled']; - if (!currentProfilerDataGroup) { - console.error('Unexpected priority', currentPriority); - } - - const startTime = (ts - reactProfilerData.startTime) / 1000; - - if (name.startsWith('--scheduler-start-')) { - if (currentPriority !== 'unscheduled') { - console.error( - `Unexpected scheduler start: "${name}" with current priority: "${currentPriority}"`, - ); - continue; // TODO Should we throw? Will this corrupt our data? - } - - currentPriority = ((name.substr(18): any): ReactPriority); - } else if (name.startsWith('--scheduler-stop-')) { - if ( - currentPriority === 'unscheduled' || - currentPriority !== name.substr(17) - ) { - console.error( - `Unexpected scheduler stop: "${name}" with current priority: "${currentPriority}"`, - ); - continue; // TODO Should we throw? Will this corrupt our data? - } - - currentPriority = 'unscheduled'; - } else if (name === '--render-start') { - if (currentMetadata.nextRenderShouldGenerateNewBatchID) { - currentMetadata.nextRenderShouldGenerateNewBatchID = false; - currentMetadata.batchUID = ((uidCounter++: any): BatchUID); - } - throwIfIncomplete('render'); - if (getLastType() !== 'render-idle') { - markWorkStarted('render-idle', startTime); - } - markWorkStarted('render', startTime); - } else if (name === '--render-stop') { - markWorkCompleted('render', startTime); - } else if (name === '--render-yield') { - markWorkCompleted('render', startTime); - } else if (name === '--render-cancel') { - currentMetadata.nextRenderShouldGenerateNewBatchID = true; - markWorkCompleted('render', startTime); - markWorkCompleted('render-idle', startTime); - } else if (name === '--commit-start') { - currentMetadata.nextRenderShouldGenerateNewBatchID = true; - markWorkStarted('commit', startTime); - } else if (name === '--commit-stop') { - markWorkCompleted('commit', startTime); - markWorkCompleted('render-idle', startTime); - } else if ( - name === '--layout-effects-start' || - name === '--passive-effects-start' - ) { - const type = - name === '--layout-effects-start' - ? 'layout-effects' - : 'passive-effects'; - markWorkStarted(type, startTime); - } else if ( - name === '--layout-effects-stop' || - name === '--passive-effects-stop' - ) { - const type = - name === '--layout-effects-stop' ? 'layout-effects' : 'passive-effects'; - markWorkCompleted(type, startTime); - } else if (name.startsWith('--schedule-render')) { - currentProfilerDataGroup.events.push({ - type: 'schedule-render', - priority: currentPriority, // TODO Change to target priority - timestamp: startTime, - }); - } else if (name.startsWith('--schedule-state-update-')) { - const [componentName, componentStack] = name.substr(24).split('-'); - const isCascading = !!currentMetadata.stack.find( - ({type}) => type === 'commit', - ); - currentProfilerDataGroup.events.push({ - type: 'schedule-state-update', - priority: currentPriority, // TODO Change to target priority - isCascading, - timestamp: startTime, - componentName, - componentStack, - }); - } else if (name.startsWith('--suspend-')) { - const [componentName, componentStack] = name.substr(10).split('-'); - currentProfilerDataGroup.events.push({ - type: 'suspend', - priority: currentPriority, // TODO Change to target priority - timestamp: startTime, - componentName, - componentStack, - }); - } - } - - Object.entries(metadata).forEach(([priority, metadataForPriority]) => { - const {stack} = ((metadataForPriority: any): Metadata); - if (stack.length > 0) { - console.error( - `Incomplete events or measures for priority ${priority}`, - stack, - ); - } - }); - - ['unscheduled', 'high', 'normal', 'low'].forEach(priority => { - const {events, measures} = reactProfilerData[priority]; - if (events.length > 0) { - const {timestamp} = (events[events.length - 1]: ReactEvent); - reactProfilerData.duration = Math.max( - reactProfilerData.duration, - timestamp, - ); - } - if (measures.length > 0) { - const {duration, timestamp} = measures[measures.length - 1]; - reactProfilerData.duration = Math.max( - reactProfilerData.duration, - timestamp + duration, - ); - } - }); - - return reactProfilerData; -} From 04e81c3f0323a9f35a272e89493981559de02a18 Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Fri, 3 Jul 2020 11:50:48 +0800 Subject: [PATCH 034/116] Rename all *V2 --- src/App.js | 21 +++++++------- src/CanvasPage.js | 28 ++++++++----------- src/EventTooltip.js | 14 +++++----- src/ImportPage.js | 18 ++++++------ src/canvas/canvasUtils.js | 6 ++-- src/canvas/renderCanvas.js | 4 +-- src/types.js | 18 ++++++------ src/util/__tests__/preprocessData-test.js | 2 +- src/util/getBatchRange.js | 4 +-- ...{preprocessDataV2.js => preprocessData.js} | 10 +++---- 10 files changed, 60 insertions(+), 65 deletions(-) rename src/util/{preprocessDataV2.js => preprocessData.js} (98%) diff --git a/src/App.js b/src/App.js index c8b2bf0d0e710..4fd0e60b67af5 100644 --- a/src/App.js +++ b/src/App.js @@ -1,6 +1,6 @@ // @flow -import type {FlamechartData, ReactLane, ReactProfilerDataV2} from './types'; +import type {FlamechartData, ReactLane, ReactProfilerData} from './types'; import React, {useState, useCallback} from 'react'; import {unstable_batchedUpdates} from 'react-dom'; @@ -11,20 +11,19 @@ import ImportPage from './ImportPage'; import CanvasPage from './CanvasPage'; export default function App() { - const [ - profilerDataV2, - setProfilerDataV2, - ] = useState(null); + const [profilerData, setProfilerData] = useState( + null, + ); const [flamechart, setFlamechart] = useState(null); const [schedulerCanvasHeight, setSchedulerCanvasHeight] = useState(0); - const handleDataImportedV2 = useCallback( + const handleDataImported = useCallback( ( - importedProfilerData: ReactProfilerDataV2, + importedProfilerData: ReactProfilerData, importedFlamechart: FlamechartData, ) => { unstable_batchedUpdates(() => { - setProfilerDataV2(importedProfilerData); + setProfilerData(importedProfilerData); setFlamechart(importedFlamechart); const lanesToRender: ReactLane[] = Array.from( @@ -40,15 +39,15 @@ export default function App() { }, ); - if (profilerDataV2 && flamechart) { + if (profilerData && flamechart) { return ( ); } else { - return ; + return ; } } diff --git a/src/CanvasPage.js b/src/CanvasPage.js index c117e4d47a4e7..4308931504c79 100644 --- a/src/CanvasPage.js +++ b/src/CanvasPage.js @@ -28,27 +28,23 @@ const CONTEXT_MENU_ID = 'canvas'; import type { FlamechartData, ReactHoverContextInfo, - ReactProfilerDataV2, + ReactProfilerData, } from './types'; type ContextMenuContextData = {| - data: ReactProfilerDataV2, + data: ReactProfilerData, flamechart: FlamechartData, hoveredEvent: ReactHoverContextInfo | null, state: PanAndZoomState, |}; type Props = {| - profilerDataV2: ReactProfilerDataV2, + profilerData: ReactProfilerData, flamechart: FlamechartData, schedulerCanvasHeight: number, |}; -function CanvasPage({ - profilerDataV2, - flamechart, - schedulerCanvasHeight, -}: Props) { +function CanvasPage({profilerData, flamechart, schedulerCanvasHeight}: Props) { return (
{({height, width}: {height: number, width: number}) => ( { }; type AutoSizedCanvasProps = {| - dataV2: ReactProfilerDataV2, + data: ReactProfilerData, flamechart: FlamechartData, height: number, schedulerCanvasHeight: number, @@ -102,7 +98,7 @@ type AutoSizedCanvasProps = {| |}; function AutoSizedCanvas({ - dataV2, + data, flamechart, height, schedulerCanvasHeight, @@ -116,7 +112,7 @@ function AutoSizedCanvas({ canvasWidth: width, fixedColumnWidth: LABEL_FIXED_WIDTH, fixedHeaderHeight: HEADER_HEIGHT_FIXED, - unscaledContentWidth: dataV2.duration, + unscaledContentWidth: data.duration, unscaledContentHeight: schedulerCanvasHeight + flamechart.layers.length * FLAMECHART_FRAME_HEIGHT, @@ -124,7 +120,7 @@ function AutoSizedCanvas({ const hoveredEvent = getHoveredEvent( schedulerCanvasHeight, - dataV2, + data, flamechart, state, ); @@ -132,7 +128,7 @@ function AutoSizedCanvas({ useContextMenu({ data: { - data: dataV2, + data, flamechart, hoveredEvent, state, @@ -145,7 +141,7 @@ function AutoSizedCanvas({ useLayoutEffect(() => { if (canvasRef.current !== null) { renderCanvas( - dataV2, + data, flamechart, canvasRef.current, width, @@ -218,7 +214,7 @@ function AutoSizedCanvas({ }} {!isContextMenuShown && ( - + )} ); diff --git a/src/EventTooltip.js b/src/EventTooltip.js index fd3faecf8a7bb..c81927aa2f2e4 100644 --- a/src/EventTooltip.js +++ b/src/EventTooltip.js @@ -3,9 +3,9 @@ import type {PanAndZoomState} from './util/usePanAndZoom'; import type {FlamechartFrame} from './speedscope/lib/flamechart'; import type { - ReactEventV2, - ReactMeasureV2, - ReactProfilerDataV2, + ReactEvent, + ReactMeasure, + ReactProfilerData, ReactHoverContextInfo, Return, } from './types'; @@ -18,7 +18,7 @@ import useSmartTooltip from './util/useSmartTooltip'; import styles from './EventTooltip.css'; type Props = {| - data: ReactProfilerDataV2, + data: ReactProfilerData, hoveredEvent: ReactHoverContextInfo | null, state: PanAndZoomState, |}; @@ -148,7 +148,7 @@ const TooltipReactEvent = ({ tooltipRef, }: { color: string, - event: ReactEventV2, + event: ReactEvent, tooltipRef: Return, }) => { const {componentName, componentStack, timestamp, type} = event; @@ -213,8 +213,8 @@ const TooltipReactMeasure = ({ measure, tooltipRef, }: { - data: ReactProfilerDataV2, - measure: ReactMeasureV2, + data: ReactProfilerData, + measure: ReactMeasure, tooltipRef: Return, }) => { const {batchUID, duration, timestamp, type} = measure; diff --git a/src/ImportPage.js b/src/ImportPage.js index 2e2e2b162d028..cff17739523aa 100644 --- a/src/ImportPage.js +++ b/src/ImportPage.js @@ -1,26 +1,26 @@ // @flow import type {TimelineEvent} from './speedscope/import/chrome'; -import type {FlamechartData, ReactProfilerDataV2} from './types'; +import type {FlamechartData, ReactProfilerData} from './types'; import React, {useEffect} from 'react'; -import preprocessDataV2 from './util/preprocessDataV2'; +import preprocessData from './util/preprocessData'; import preprocessFlamechart from './util/preprocessFlamechart'; // TODO: Add import button but keep a static path until canvas layout is ready -import JSON_PATHV2 from 'url:../static/Profile-20200625T133129.json'; +import JSON_PATH from 'url:../static/Profile-20200625T133129.json'; type Props = {| - onDataImportedV2: ( - profilerData: ReactProfilerDataV2, + onDataImported: ( + profilerData: ReactProfilerData, flamechart: FlamechartData, ) => void, |}; -export default function ImportPage({onDataImportedV2}: Props) { +export default function ImportPage({onDataImported}: Props) { useEffect(() => { - fetch(JSON_PATHV2) + fetch(JSON_PATH) .then(res => res.json()) .then((events: TimelineEvent[]) => { // Filter null entries and sort by timestamp. @@ -29,9 +29,9 @@ export default function ImportPage({onDataImportedV2}: Props) { events = events.filter(Boolean).sort((a, b) => (a.ts > b.ts ? 1 : -1)); if (events.length > 0) { - const processedData = preprocessDataV2(events); + const processedData = preprocessData(events); const processedFlamechart = preprocessFlamechart(events); - onDataImportedV2(processedData, processedFlamechart); + onDataImported(processedData, processedFlamechart); } }); }, []); diff --git a/src/canvas/canvasUtils.js b/src/canvas/canvasUtils.js index babdd23bcfa95..59f11d75c4586 100644 --- a/src/canvas/canvasUtils.js +++ b/src/canvas/canvasUtils.js @@ -5,7 +5,7 @@ import type { FlamechartData, ReactHoverContextInfo, ReactLane, - ReactProfilerDataV2, + ReactProfilerData, } from '../types'; import type {PanAndZoomState} from '../util/usePanAndZoom'; @@ -110,7 +110,7 @@ export const trimFlamegraphText = ( export function getHoveredEvent( schedulerCanvasHeight: number, - data: $ReadOnly, + data: $ReadOnly, flamechart: $ReadOnly, state: PanAndZoomState, ): ReactHoverContextInfo | null { @@ -243,7 +243,7 @@ export function getHoveredEvent( } export const getLaneHeight = ( - data: $ReadOnly, + data: $ReadOnly, lane: ReactLane, ): number => { // TODO: Return 0 if data has no data for lane diff --git a/src/canvas/renderCanvas.js b/src/canvas/renderCanvas.js index 535a92775c07f..d792189891233 100644 --- a/src/canvas/renderCanvas.js +++ b/src/canvas/renderCanvas.js @@ -4,7 +4,7 @@ import type { FlamechartData, ReactHoverContextInfo, ReactLane, - ReactProfilerDataV2, + ReactProfilerData, } from '../types'; import type {PanAndZoomState} from '../util/usePanAndZoom'; @@ -507,7 +507,7 @@ function renderAxisMarkers( // TODO Passing "state" directly breaks memoization for e.g. mouse moves export const renderCanvas = memoize( ( - data: $ReadOnly, + data: $ReadOnly, flamechart: $ReadOnly, canvas: HTMLCanvasElement, canvasWidth: number, diff --git a/src/types.js b/src/types.js index 557bfa369425f..66ebf68054868 100644 --- a/src/types.js +++ b/src/types.js @@ -58,14 +58,14 @@ export type ReactSuspenseRejectedEvent = {| type: 'suspense-rejected', |}; -export type ReactEventV2 = +export type ReactEvent = | ReactScheduleRenderEvent | ReactScheduleStateUpdateEvent | ReactScheduleForceUpdateEvent | ReactSuspenseSuspendEvent | ReactSuspenseResolvedEvent | ReactSuspenseRejectedEvent; -export type ReactEventTypeV2 = $PropertyType; +export type ReactEventType = $PropertyType; export type ReactMeasureType = | 'commit' @@ -78,7 +78,7 @@ export type ReactMeasureType = export type BatchUID = number; -export type ReactMeasureV2 = {| +export type ReactMeasure = {| +type: ReactMeasureType, +lanes: ReactLane[], +timestamp: Milliseconds, @@ -87,18 +87,18 @@ export type ReactMeasureV2 = {| +depth: number, |}; -export type ReactProfilerDataV2 = {| +export type ReactProfilerData = {| startTime: number, duration: number, - events: ReactEventV2[], - measures: ReactMeasureV2[], + events: ReactEvent[], + measures: ReactMeasure[], |}; export type ReactHoverContextInfo = {| - event: ReactEventV2 | null, - measure: ReactMeasureV2 | null, + event: ReactEvent | null, + measure: ReactMeasure | null, lane: ReactLane | null, - data: $ReadOnly | null, + data: $ReadOnly | null, flamechartNode: FlamechartFrame | null, |}; diff --git a/src/util/__tests__/preprocessData-test.js b/src/util/__tests__/preprocessData-test.js index f84a540eee7b5..d77c8d3b3dc00 100644 --- a/src/util/__tests__/preprocessData-test.js +++ b/src/util/__tests__/preprocessData-test.js @@ -2,7 +2,7 @@ import preprocessData, { getLanesFromTransportDecimalBitmask, -} from '../preprocessDataV2'; +} from '../preprocessData'; import {REACT_TOTAL_NUM_LANES} from '../../constants'; // Disable quotes rule in the whole file as we paste raw JSON as test inputs and diff --git a/src/util/getBatchRange.js b/src/util/getBatchRange.js index 393766940002c..023f2591fe438 100644 --- a/src/util/getBatchRange.js +++ b/src/util/getBatchRange.js @@ -2,14 +2,14 @@ import memoize from 'memoize-one'; -import type {BatchUID, Milliseconds, ReactProfilerDataV2} from '../types'; +import type {BatchUID, Milliseconds, ReactProfilerData} from '../types'; // TODO Batch duration probably shouldn't include delayed passive effects? // It should probably end with the layout effect. function unmemoizedGetBatchRange( batchUID: BatchUID, - data: ReactProfilerDataV2, + data: ReactProfilerData, ): [Milliseconds, Milliseconds] { const {measures} = data; diff --git a/src/util/preprocessDataV2.js b/src/util/preprocessData.js similarity index 98% rename from src/util/preprocessDataV2.js rename to src/util/preprocessData.js index e9a08e770ab87..8994989e807f4 100644 --- a/src/util/preprocessDataV2.js +++ b/src/util/preprocessData.js @@ -6,7 +6,7 @@ import type { BatchUID, ReactLane, ReactMeasureType, - ReactProfilerDataV2, + ReactProfilerData, } from '../types'; import {REACT_TOTAL_NUM_LANES} from '../constants'; @@ -69,7 +69,7 @@ function markWorkStarted( type: ReactMeasureType, startTime: Milliseconds, lanes: ReactLane[], - currentProfilerData: ReactProfilerDataV2, + currentProfilerData: ReactProfilerData, state: ProcessorState, ) { const {batchUID, measureStack} = state; @@ -91,7 +91,7 @@ function markWorkStarted( function markWorkCompleted( type: ReactMeasureType, stopTime: Milliseconds, - currentProfilerData: ReactProfilerDataV2, + currentProfilerData: ReactProfilerData, stack: $PropertyType, ) { if (stack.length === 0) { @@ -137,7 +137,7 @@ function throwIfIncomplete( function processTimelineEvent( event: TimelineEvent, /** Finalized profiler data up to `event`. May be mutated. */ - currentProfilerData: ReactProfilerDataV2, + currentProfilerData: ReactProfilerData, /** Intermediate processor state. May be mutated. */ state: ProcessorState, ) { @@ -350,7 +350,7 @@ function processTimelineEvent( export default function preprocessData( timeline: TimelineEvent[], -): ReactProfilerDataV2 { +): ReactProfilerData { const profilerData = { startTime: 0, duration: 0, From cc0dec38848221ac3292405d579e81ee0082498a Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Fri, 3 Jul 2020 21:58:14 +0800 Subject: [PATCH 035/116] [Canvas V2][5/n] Improve getHoveredEvent clarity (#40) --- src/CanvasPage.js | 2 +- src/canvas/canvasUtils.js | 152 +-------------------- src/canvas/getHoveredEvent.js | 241 ++++++++++++++++++++++++++++++++++ 3 files changed, 243 insertions(+), 152 deletions(-) create mode 100644 src/canvas/getHoveredEvent.js diff --git a/src/CanvasPage.js b/src/CanvasPage.js index 4308931504c79..74eaf1fb0fc24 100644 --- a/src/CanvasPage.js +++ b/src/CanvasPage.js @@ -6,7 +6,7 @@ import {copy} from 'clipboard-js'; import React, {Fragment, useLayoutEffect, useRef, useState} from 'react'; import usePanAndZoom from './util/usePanAndZoom'; -import {getHoveredEvent} from './canvas/canvasUtils'; +import {getHoveredEvent} from './canvas/getHoveredEvent'; import {renderCanvas} from './canvas/renderCanvas'; import prettyMilliseconds from 'pretty-ms'; diff --git a/src/canvas/canvasUtils.js b/src/canvas/canvasUtils.js index 59f11d75c4586..1bec3f3327278 100644 --- a/src/canvas/canvasUtils.js +++ b/src/canvas/canvasUtils.js @@ -1,32 +1,16 @@ // @flow // Contains helper functions for rendering canvas elements -import type { - FlamechartData, - ReactHoverContextInfo, - ReactLane, - ReactProfilerData, -} from '../types'; -import type {PanAndZoomState} from '../util/usePanAndZoom'; +import type {ReactLane, ReactProfilerData} from '../types'; import memoize from 'memoize-one'; import { INTERVAL_TIMES, MAX_INTERVAL_SIZE_PX, - HEADER_HEIGHT_FIXED, REACT_GUTTER_SIZE, - REACT_EVENT_SIZE, REACT_WORK_SIZE, REACT_PRIORITY_BORDER_SIZE, - FLAMECHART_FRAME_HEIGHT, - EVENT_ROW_HEIGHT_FIXED, } from './constants'; -import { - durationToWidth, - positionToTimestamp, - timestampToPosition, -} from '../util/usePanAndZoom'; -import {REACT_TOTAL_NUM_LANES} from '../constants'; // hidpi canvas: https://www.html5rocks.com/en/tutorials/canvas/hidpi/ function configureRetinaCanvas(canvas, height, width) { @@ -108,140 +92,6 @@ export const trimFlamegraphText = ( return null; }; -export function getHoveredEvent( - schedulerCanvasHeight: number, - data: $ReadOnly, - flamechart: $ReadOnly, - state: PanAndZoomState, -): ReactHoverContextInfo | null { - const {canvasMouseX, canvasMouseY, offsetY} = state; - - if (canvasMouseY < HEADER_HEIGHT_FIXED) { - return null; - } - - if (canvasMouseY + offsetY < HEADER_HEIGHT_FIXED + EVENT_ROW_HEIGHT_FIXED) { - // Find hovered React event - - const {events} = data; - - // Because data ranges may overlap, we want to find the last intersecting item. - // This will always be the one on "top" (the one the user is hovering over). - for (let index = events.length - 1; index >= 0; index--) { - const event = events[index]; - const {timestamp} = event; - - const eventX = timestampToPosition(timestamp, state); - const startX = eventX - REACT_EVENT_SIZE / 2; - const stopX = eventX + REACT_EVENT_SIZE / 2; - if (canvasMouseX >= startX && canvasMouseX <= stopX) { - return { - event, - flamechartNode: null, - measure: null, - lane: null, - data, - }; - } - } - } else if ( - canvasMouseY + offsetY < - HEADER_HEIGHT_FIXED + EVENT_ROW_HEIGHT_FIXED + schedulerCanvasHeight - ) { - // Find hovered React measure - - const adjustedCanvasMouseY = canvasMouseY - HEADER_HEIGHT_FIXED + offsetY; - let laneMinY = EVENT_ROW_HEIGHT_FIXED; - let lane = null; - for ( - let laneIndex: ReactLane = 0; - laneIndex < REACT_TOTAL_NUM_LANES; - laneIndex++ - ) { - const laneHeight = getLaneHeight(data, laneIndex); - if ( - adjustedCanvasMouseY >= laneMinY && - adjustedCanvasMouseY <= laneMinY + laneHeight - ) { - lane = laneIndex; - break; - } - laneMinY += laneHeight; - } - - if (lane === null) { - return null; - } - - // Because data ranges may overlap, we want to find the last intersecting item. - // This will always be the one on "top" (the one the user is hovering over). - const {measures} = data; - for (let index = measures.length - 1; index >= 0; index--) { - const measure = measures[index]; - if (!measure.lanes.includes(lane)) { - continue; - } - - const {duration, timestamp} = measure; - const pointerTime = positionToTimestamp(canvasMouseX, state); - - if (pointerTime >= timestamp && pointerTime <= timestamp + duration) { - return { - event: null, - flamechartNode: null, - measure, - lane, - data, - }; - } - } - } else { - // Find hovered flamechart event - - const layerIndex = Math.floor( - (canvasMouseY + - offsetY - - HEADER_HEIGHT_FIXED - - EVENT_ROW_HEIGHT_FIXED - - schedulerCanvasHeight) / - FLAMECHART_FRAME_HEIGHT, - ); - const layer = flamechart.layers[layerIndex]; - - if (layer != null) { - let startIndex = 0; - let stopIndex = layer.length - 1; - while (startIndex <= stopIndex) { - const currentIndex = Math.floor((startIndex + stopIndex) / 2); - const flamechartNode = layer[currentIndex]; - - const {end, start} = flamechartNode; - - const width = durationToWidth((end - start) / 1000, state); - const x = Math.floor(timestampToPosition(start / 1000, state)); - - if (x <= canvasMouseX && x + width >= canvasMouseX) { - return { - event: null, - flamechartNode, - measure: null, - lane: null, - data, - }; - } - - if (x > canvasMouseX) { - stopIndex = currentIndex - 1; - } else { - startIndex = currentIndex + 1; - } - } - } - } - - return null; -} - export const getLaneHeight = ( data: $ReadOnly, lane: ReactLane, diff --git a/src/canvas/getHoveredEvent.js b/src/canvas/getHoveredEvent.js new file mode 100644 index 0000000000000..c23d56337f59f --- /dev/null +++ b/src/canvas/getHoveredEvent.js @@ -0,0 +1,241 @@ +// @flow + +import type { + FlamechartData, + ReactHoverContextInfo, + ReactLane, + ReactProfilerData, +} from '../types'; +import type {PanAndZoomState} from '../util/usePanAndZoom'; + +import { + durationToWidth, + positionToTimestamp, + timestampToPosition, +} from '../util/usePanAndZoom'; +import {REACT_TOTAL_NUM_LANES} from '../constants'; + +import {getLaneHeight} from './canvasUtils'; +import { + HEADER_HEIGHT_FIXED, + REACT_EVENT_SIZE, + FLAMECHART_FRAME_HEIGHT, + EVENT_ROW_HEIGHT_FIXED, +} from './constants'; + +/** + * Returns a hover context info object containing the `ReactEvent` currently + * being hovered over. + * + * NOTE: Assumes that the events are all in a row, and that the cursor is + * already known to be in this row; this function only compares the X positions + * of the cursor and events. + */ +function getHoveredReactEvent( + data: $ReadOnly, + panAndZoomState: PanAndZoomState, +): ReactHoverContextInfo | null { + const {canvasMouseX} = panAndZoomState; + const {events} = data; + + // Because data ranges may overlap, we want to find the last intersecting item. + // This will always be the one on "top" (the one the user is hovering over). + for (let index = events.length - 1; index >= 0; index--) { + const event = events[index]; + const {timestamp} = event; + + const eventX = timestampToPosition(timestamp, panAndZoomState); + const startX = eventX - REACT_EVENT_SIZE / 2; + const stopX = eventX + REACT_EVENT_SIZE / 2; + if (canvasMouseX >= startX && canvasMouseX <= stopX) { + return { + event, + flamechartNode: null, + measure: null, + lane: null, + data, + }; + } + } + + return null; +} + +/** + * Returns a hover context info object containing the `ReactMeasure` currently + * being hovered over. + */ +function getHoveredReactMeasure( + data: $ReadOnly, + panAndZoomState: PanAndZoomState, + stackSectionBaseY: number, +): ReactHoverContextInfo | null { + const {canvasMouseX, canvasMouseY, offsetY} = panAndZoomState; + + // Identify the lane being hovered over + const adjustedCanvasMouseY = canvasMouseY - stackSectionBaseY + offsetY; + let laneMinY = 0; + let lane = null; + for ( + let laneIndex: ReactLane = 0; + laneIndex < REACT_TOTAL_NUM_LANES; + laneIndex++ + ) { + const laneHeight = getLaneHeight(data, laneIndex); + if ( + adjustedCanvasMouseY >= laneMinY && + adjustedCanvasMouseY <= laneMinY + laneHeight + ) { + lane = laneIndex; + break; + } + laneMinY += laneHeight; + } + + if (lane === null) { + return null; + } + + // Find the measure in `lane` being hovered over. + // + // Because data ranges may overlap, we want to find the last intersecting item. + // This will always be the one on "top" (the one the user is hovering over). + const {measures} = data; + for (let index = measures.length - 1; index >= 0; index--) { + const measure = measures[index]; + if (!measure.lanes.includes(lane)) { + continue; + } + + const {duration, timestamp} = measure; + const pointerTime = positionToTimestamp(canvasMouseX, panAndZoomState); + + if (pointerTime >= timestamp && pointerTime <= timestamp + duration) { + return { + event: null, + flamechartNode: null, + measure, + lane, + data, + }; + } + } + + return null; +} + +/** + * Returns a hover context info object containing the `FlamechartFrame` + * currently being hovered over. + */ +function getHoveredFlamechartEvent( + data: $ReadOnly, + flamechart: $ReadOnly, + panAndZoomState: PanAndZoomState, + stackSectionBaseY: number, +): ReactHoverContextInfo | null { + const {canvasMouseX, canvasMouseY, offsetY} = panAndZoomState; + + const layerIndex = Math.floor( + (canvasMouseY + offsetY - stackSectionBaseY) / FLAMECHART_FRAME_HEIGHT, + ); + const layer = flamechart.layers[layerIndex]; + + if (!layer) { + return null; + } + + let startIndex = 0; + let stopIndex = layer.length - 1; + while (startIndex <= stopIndex) { + const currentIndex = Math.floor((startIndex + stopIndex) / 2); + const flamechartNode = layer[currentIndex]; + + const {end, start} = flamechartNode; + + const width = durationToWidth((end - start) / 1000, panAndZoomState); + const x = Math.floor(timestampToPosition(start / 1000, panAndZoomState)); + + if (x <= canvasMouseX && x + width >= canvasMouseX) { + return { + event: null, + flamechartNode, + measure: null, + lane: null, + data, + }; + } + + if (x > canvasMouseX) { + stopIndex = currentIndex - 1; + } else { + startIndex = currentIndex + 1; + } + } + + return null; +} + +/** + * Returns a hover context object if the cursor is hovering over a React + * event/measure or a Flamechart node, otherwise returns null. + */ +export function getHoveredEvent( + schedulerCanvasHeight: number, + data: $ReadOnly, + flamechart: $ReadOnly, + panAndZoomState: PanAndZoomState, +): ReactHoverContextInfo | null { + const {canvasMouseY, offsetY} = panAndZoomState; + + // These variables keep track of the current vertical stack sections' base and + // max Y coordinates. For example, if we're at the React event row, these are + // what the values represent: + // ┌----------------------------------- + // | t⁰ t¹ t² ... + // ├---------------------------------- <- stackSectionBaseY + // | + // | + // | + // ├---------------------------------- <- stackSectionMaxY + // | + // | + // | + // ├---------------------------------- + // | + // | + // | + // └---------------------------------- + let stackSectionBaseY: number; + let stackSectionMaxY: number = 0; + + // Header section: do nothing + stackSectionBaseY = stackSectionMaxY; + stackSectionMaxY += HEADER_HEIGHT_FIXED; + if (canvasMouseY < stackSectionMaxY) { + return null; + } + + // ReactEvent row + stackSectionBaseY = stackSectionMaxY; + stackSectionMaxY += EVENT_ROW_HEIGHT_FIXED; + if (canvasMouseY + offsetY < stackSectionMaxY) { + return getHoveredReactEvent(data, panAndZoomState); + } + + // ReactMeasure lanes + stackSectionBaseY = stackSectionMaxY; + stackSectionMaxY += schedulerCanvasHeight; + if (canvasMouseY + offsetY < stackSectionMaxY) { + return getHoveredReactMeasure(data, panAndZoomState, stackSectionBaseY); + } + + // Flamechart area + stackSectionBaseY = stackSectionMaxY; + return getHoveredFlamechartEvent( + data, + flamechart, + panAndZoomState, + stackSectionBaseY, + ); +} From b72cdda702fd8f8dbeb5932516a31d2bd4257afe Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Wed, 8 Jul 2020 15:12:17 +0800 Subject: [PATCH 036/116] Fix React data and flamegraph alignment (#53) * Replace Speedscope fork with custom forked package * Remove unused tracerbench * Fix wrong abort if one flamechart node is too narrow * Fix startTime and duration computation * Fix tests * Lock @elg/speedscope version --- package.json | 1 + src/EventTooltip.js | 2 +- src/ImportPage.js | 2 +- src/canvas/renderCanvas.js | 2 +- src/speedscope/README.md | 1 - src/speedscope/import/chrome.js | 275 -------- src/speedscope/import/v8cpuFormatter.js | 39 -- src/speedscope/lib/demangle-cpp.js | 32 - src/speedscope/lib/file-format-spec.js | 13 - src/speedscope/lib/flamechart.js | 137 ---- src/speedscope/lib/math.js | 302 --------- src/speedscope/lib/profile.js | 604 ------------------ src/speedscope/lib/utils.js | 254 -------- src/speedscope/lib/value-formatters.js | 59 -- src/tracerbench/trace/bounds.js | 27 - src/tracerbench/trace/cpu-profile.js | 316 --------- src/tracerbench/trace/index.js | 10 - src/tracerbench/trace/process.js | 26 - src/tracerbench/trace/render-events.js | 138 ---- src/tracerbench/trace/thread.js | 12 - src/tracerbench/trace/trace.js | 292 --------- src/tracerbench/trace/trace_event.js | 54 -- .../trace/trace_event_comparator.js | 34 - src/types.js | 2 +- .../__snapshots__/preprocessData-test.js.snap | 318 ++++----- src/util/__tests__/preprocessData-test.js | 30 +- src/util/preprocessData.js | 44 +- src/util/preprocessFlamechart.js | 7 +- yarn.lock | 20 + 29 files changed, 231 insertions(+), 2822 deletions(-) delete mode 100644 src/speedscope/README.md delete mode 100644 src/speedscope/import/chrome.js delete mode 100644 src/speedscope/import/v8cpuFormatter.js delete mode 100644 src/speedscope/lib/demangle-cpp.js delete mode 100644 src/speedscope/lib/file-format-spec.js delete mode 100644 src/speedscope/lib/flamechart.js delete mode 100644 src/speedscope/lib/math.js delete mode 100644 src/speedscope/lib/profile.js delete mode 100644 src/speedscope/lib/utils.js delete mode 100644 src/speedscope/lib/value-formatters.js delete mode 100644 src/tracerbench/trace/bounds.js delete mode 100644 src/tracerbench/trace/cpu-profile.js delete mode 100644 src/tracerbench/trace/index.js delete mode 100644 src/tracerbench/trace/process.js delete mode 100644 src/tracerbench/trace/render-events.js delete mode 100644 src/tracerbench/trace/thread.js delete mode 100644 src/tracerbench/trace/trace.js delete mode 100644 src/tracerbench/trace/trace_event.js delete mode 100644 src/tracerbench/trace/trace_event_comparator.js diff --git a/package.json b/package.json index a075cf0894037..a572f9215eef2 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "author": "Brian Vaughn ", "license": "MIT", "dependencies": { + "@elg/speedscope": "1.6.0-787837d", "array-binsearch": "^1.0.1", "clipboard-js": "^0.3.6", "d3-hierarchy": "^1.1.9", diff --git a/src/EventTooltip.js b/src/EventTooltip.js index c81927aa2f2e4..23487d1685483 100644 --- a/src/EventTooltip.js +++ b/src/EventTooltip.js @@ -1,7 +1,7 @@ // @flow import type {PanAndZoomState} from './util/usePanAndZoom'; -import type {FlamechartFrame} from './speedscope/lib/flamechart'; +import type {FlamechartFrame} from '@elg/speedscope'; import type { ReactEvent, ReactMeasure, diff --git a/src/ImportPage.js b/src/ImportPage.js index cff17739523aa..b62d5f1879e8b 100644 --- a/src/ImportPage.js +++ b/src/ImportPage.js @@ -1,6 +1,6 @@ // @flow -import type {TimelineEvent} from './speedscope/import/chrome'; +import type {TimelineEvent} from '@elg/speedscope'; import type {FlamechartData, ReactProfilerData} from './types'; import React, {useEffect} from 'react'; diff --git a/src/canvas/renderCanvas.js b/src/canvas/renderCanvas.js index d792189891233..13d2291d16f57 100644 --- a/src/canvas/renderCanvas.js +++ b/src/canvas/renderCanvas.js @@ -412,7 +412,7 @@ function renderFlamechart( const width = durationToWidth((end - start) / 1000, state); if (width <= 0) { - return; // Too small to render at this zoom level + continue; // Too small to render at this zoom level } const x = Math.floor(timestampToPosition(start / 1000, state)); diff --git a/src/speedscope/README.md b/src/speedscope/README.md deleted file mode 100644 index 6b116be77c71f..0000000000000 --- a/src/speedscope/README.md +++ /dev/null @@ -1 +0,0 @@ -https://github.com/jlfwong/speedscope/ \ No newline at end of file diff --git a/src/speedscope/import/chrome.js b/src/speedscope/import/chrome.js deleted file mode 100644 index f79c0df3ed918..0000000000000 --- a/src/speedscope/import/chrome.js +++ /dev/null @@ -1,275 +0,0 @@ -// @flow - -import { - Profile, - FrameInfo, - CallTreeProfileBuilder, - ProfileGroup, -} from '../lib/profile'; -import { getOrInsert, lastOf, sortBy, itForEach } from '../lib/utils'; -import { TimeFormatter } from '../lib/value-formatters'; -import { chromeTreeToNodes, OldCPUProfile } from './v8cpuFormatter'; - -// See: https://github.com/v8/v8/blob/master/src/inspector/js_protocol.json - -export interface TimelineEvent { - pid: number; - tid: number; - ts: number; - ph: string; - cat: string; - name: string; - dur: number; - tdur: number; - tts: number; - args: { [key: string]: any }; - id?: String; -} - -export function isChromeTimeline(rawProfile) { - if (!Array.isArray(rawProfile)) return false; - if (rawProfile.length < 1) return false; - const first = rawProfile[0]; - if (!('pid' in first && 'tid' in first && 'ph' in first && 'cat' in first)) - return false; - if ( - !rawProfile.find( - e => - e.name === 'CpuProfile' || - e.name === 'Profile' || - e.name === 'ProfileChunk' - ) - ) - return false; - return true; -} -export function importFromChromeTimeline( - events: TimelineEvent[], - fileName: string -): ProfileGroup { - // It seems like sometimes Chrome timeline files contain multiple CpuProfiles? - // For now, choose the first one in the list. - const cpuProfileByID = new Map(); - // Maps profile IDs (like "0x3") to pid/tid pairs formatted as `${pid}:${tid}` - const pidTidById = new Map(); - // Maps pid/tid pairs to thread names - const threadNameByPidTid = new Map(); - // The events aren't necessarily recorded in chronological order. Sort them so - // that they are. - sortBy(events, e => e.ts); - for (let event of events) { - if (event.name === 'CpuProfile') { - const pidTid = `${event.pid}:${event.tid}`; - const id = event.id || pidTid; - cpuProfileByID.set(id, event.args.data.cpuProfile); - pidTidById.set(id, pidTid); - } - if (event.name === 'Profile') { - const pidTid = `${event.pid}:${event.tid}`; - cpuProfileByID.set( - event.id || pidTid, - Object.assign( - { startTime: 0, endTime: 0, nodes: [], samples: [], timeDeltas: [] }, - event.args.data - ) - ); - if (event.id) { - pidTidById.set(event.id, `${event.pid}:${event.tid}`); - } - } - if (event.name === 'thread_name') { - threadNameByPidTid.set(`${event.pid}:${event.tid}`, event.args.name); - } - if (event.name === 'ProfileChunk') { - const pidTid = `${event.pid}:${event.tid}`; - const cpuProfile = cpuProfileByID.get(event.id || pidTid); - if (cpuProfile) { - const chunk = event.args.data; - if (chunk.cpuProfile) { - if (chunk.cpuProfile.nodes) { - cpuProfile.nodes = cpuProfile.nodes.concat(chunk.cpuProfile.nodes); - } - if (chunk.cpuProfile.samples) { - cpuProfile.samples = cpuProfile.samples.concat( - chunk.cpuProfile.samples - ); - } - } - if (chunk.timeDeltas) { - cpuProfile.timeDeltas = cpuProfile.timeDeltas.concat( - chunk.timeDeltas - ); - } - if (chunk.startTime != null) { - cpuProfile.startTime = chunk.startTime; - } - if (chunk.endTime != null) { - cpuProfile.endTime = chunk.endTime; - } - } else { - console.warn( - `Ignoring ProfileChunk for undeclared Profile with id ${event.id || - pidTid}` - ); - } - } - } - if (cpuProfileByID.size > 0) { - const profiles = []; - let indexToView = 0; - itForEach(cpuProfileByID.keys(), profileId => { - let threadName = null; - let pidTid = pidTidById.get(profileId); - if (pidTid) { - threadName = threadNameByPidTid.get(pidTid) || null; - if (threadName) { - } - } - const profile = importFromChromeCPUProfile(cpuProfileByID.get(profileId)); - if (threadName && cpuProfileByID.size > 1) { - profile.setName(`${fileName} - ${threadName}`); - if (threadName === 'CrRendererMain') { - indexToView = profiles.length; - } - } else { - profile.setName(`${fileName}`); - } - profiles.push(profile); - }); - return { name: fileName, indexToView, profiles }; - } else { - throw new Error('Could not find CPU profile in Timeline'); - } -} -const callFrameToFrameInfo = new Map(); -function frameInfoForCallFrame(callFrame) { - return getOrInsert(callFrameToFrameInfo, callFrame, callFrame => { - const name = callFrame.functionName || '(anonymous)'; - const file = callFrame.url; - const line = callFrame.lineNumber; - const col = callFrame.columnNumber; - return { - key: `${name}:${file}:${line}:${col}`, - name, - file, - line, - col, - }; - }); -} -function shouldIgnoreFunction(callFrame) { - const { functionName, url } = callFrame; - if (url === 'native dummy.js') { - // I'm not really sure what this is about, but this seems to be used - // as a way of avoiding edge cases in V8's implementation. - // See: https://github.com/v8/v8/blob/b8626ca4/tools/js2c.py#L419-L424 - return true; - } - return functionName === '(root)' || functionName === '(idle)'; -} -function shouldPlaceOnTopOfPreviousStack(functionName) { - return functionName === '(garbage collector)' || functionName === '(program)'; -} -export function importFromChromeCPUProfile(chromeProfile) { - const profile = new CallTreeProfileBuilder( - chromeProfile.endTime - chromeProfile.startTime - ); - const nodeById = new Map(); - for (let node of chromeProfile.nodes) { - nodeById.set(node.id, node); - } - for (let node of chromeProfile.nodes) { - if (typeof node.parent === 'number') { - node.parent = nodeById.get(node.parent); - } - if (!node.children) continue; - for (let childId of node.children) { - const child = nodeById.get(childId); - if (!child) continue; - child.parent = node; - } - } - const samples = []; - const sampleTimes = []; - // The first delta is relative to the profile startTime. - // Ref: https://github.com/v8/v8/blob/44bd8fd7/src/inspector/js_protocol.json#L1485 - let elapsed = chromeProfile.timeDeltas[0]; - let lastNodeId = NaN; - // The chrome CPU profile format doesn't collapse identical samples. We'll do that - // here to save a ton of work later doing mergers. - for (let i = 0; i < chromeProfile.samples.length; i++) { - const nodeId = chromeProfile.samples[i]; - if (nodeId != lastNodeId) { - samples.push(nodeId); - sampleTimes.push(elapsed); - } - if (i === chromeProfile.samples.length - 1) { - if (!isNaN(lastNodeId)) { - samples.push(lastNodeId); - sampleTimes.push(elapsed); - } - } else { - let timeDelta = chromeProfile.timeDeltas[i + 1]; - if (timeDelta < 0) { - // This is super noisy, but can be helpful when debugging strange data - // console.warn('Substituting zero for unexpected time delta:', timeDelta, 'at index', i) - timeDelta = 0; - } - elapsed += timeDelta; - lastNodeId = nodeId; - } - } - let prevStack = []; - for (let i = 0; i < samples.length; i++) { - const value = sampleTimes[i]; - const nodeId = samples[i]; - let stackTop = nodeById.get(nodeId); - if (!stackTop) continue; - // Find lowest common ancestor of the current stack and the previous one - let lca = null; - // This is O(n^2), but n should be relatively small here (stack height), - // so hopefully this isn't much of a problem - for ( - lca = stackTop; - lca && prevStack.indexOf(lca) === -1; - lca = shouldPlaceOnTopOfPreviousStack(lca.callFrame.functionName) - ? lastOf(prevStack) - : lca.parent || null - ) {} - // Close frames that are no longer open - while (prevStack.length > 0 && lastOf(prevStack) != lca) { - const closingNode = prevStack.pop(); - const frame = frameInfoForCallFrame(closingNode.callFrame); - profile.leaveFrame(frame, value); - } - // Open frames that are now becoming open - const toOpen = []; - for ( - let node = stackTop; - node && node != lca && !shouldIgnoreFunction(node.callFrame); - // Place Chrome internal functions on top of the previous call stack - node = shouldPlaceOnTopOfPreviousStack(node.callFrame.functionName) - ? lastOf(prevStack) - : node.parent || null - ) { - toOpen.push(node); - } - toOpen.reverse(); - for (let node of toOpen) { - profile.enterFrame(frameInfoForCallFrame(node.callFrame), value); - } - prevStack = prevStack.concat(toOpen); - } - // Close frames that are open at the end of the trace - for (let i = prevStack.length - 1; i >= 0; i--) { - profile.leaveFrame( - frameInfoForCallFrame(prevStack[i].callFrame), - lastOf(sampleTimes) - ); - } - profile.setValueFormatter(new TimeFormatter('microseconds')); - return profile.build(); -} -export function importFromOldV8CPUProfile(content) { - return importFromChromeCPUProfile(chromeTreeToNodes(content)); -} diff --git a/src/speedscope/import/v8cpuFormatter.js b/src/speedscope/import/v8cpuFormatter.js deleted file mode 100644 index 9443c98d2e2fd..0000000000000 --- a/src/speedscope/import/v8cpuFormatter.js +++ /dev/null @@ -1,39 +0,0 @@ -function treeToArray(root) { - const nodes = []; - function visit(node) { - nodes.push({ - id: node.id, - callFrame: { - columnNumber: 0, - functionName: node.functionName, - lineNumber: node.lineNumber, - scriptId: node.scriptId, - url: node.url, - }, - hitCount: node.hitCount, - children: node.children.map(child => child.id), - }); - node.children.forEach(visit); - } - visit(root); - return nodes; -} -function timestampsToDeltas(timestamps, startTime) { - return timestamps.map((timestamp, index) => { - const lastTimestamp = index === 0 ? startTime * 1000000 : timestamps[index - 1]; - return timestamp - lastTimestamp; - }); -} -/** - * Convert the old tree-based format to the new flat-array based format - */ -export function chromeTreeToNodes(content) { - // Note that both startTime and endTime are now in microseconds - return { - samples: content.samples, - startTime: content.startTime * 1000000, - endTime: content.endTime * 1000000, - nodes: treeToArray(content.head), - timeDeltas: timestampsToDeltas(content.timestamps, content.startTime), - }; -} diff --git a/src/speedscope/lib/demangle-cpp.js b/src/speedscope/lib/demangle-cpp.js deleted file mode 100644 index c4ec613c95ab3..0000000000000 --- a/src/speedscope/lib/demangle-cpp.js +++ /dev/null @@ -1,32 +0,0 @@ -let cppfilt; -const cache = new Map(); -// This function converts a mangled C++ name such as "__ZNK7Support6ColorFeqERKS0_" -// into a human-readable symbol (in this case "Support::ColorF::==(Support::ColorF&)") -export function demangleCpp(name) { - if (name.startsWith('__Z')) { - let result = cache.get(name); - if (result !== undefined) { - name = result; - } - else { - if (!cppfilt) { - cppfilt = new Function('exports', code)(); - } - result = cppfilt(name.slice(1)); - result = result === '(null)' ? name : result; - cache.set(name, result); - name = result; - } - } - return name; -} - -// This was taken from https://d.fuqu.jp/c++filtjs/ -const code = ` -return function(){function r(r){eval.call(null,r)}function a(r){throw print(r+":\\n"+(new Error).stack),ke=!0,"Assertion: "+r}function e(r,e){r||a("Assertion failed: "+e)}function i(r,a,i,v){function t(r,a){if("string"==a){var e=Oe;return le.stackAlloc(r.length+1),A(r,e),e}return r}function f(r,a){return"string"==a?s(r):r}try{func=ce.Module["_"+r]}catch(r){}e(func,"Cannot call unknown function "+r+" (perhaps LLVM optimizations or closure removed it?)");var _=0,n=v?v.map(function(r){return t(r,i[_++])}):[];return f(func.apply(null,n),a)}function v(r,a,e){return function(){return i(r,a,e,Array.prototype.slice.call(arguments))}}function t(r,e,i,v){switch(i=i||"i8","*"===i[i.length-1]&&(i="i32"),i){case"i1":Ae[r]=e;break;case"i8":Ae[r]=e;break;case"i16":ye[r>>1]=e;break;case"i32":Se[r>>2]=e;break;case"i64":Se[r>>2]=e;break;case"float":Ce[r>>2]=e;break;case"double":ze[0]=e,Se[r>>2]=xe[0],Se[r+4>>2]=xe[1];break;default:a("invalid type for setValue: "+i)}}function f(r,e,i){switch(e=e||"i8","*"===e[e.length-1]&&(e="i32"),e){case"i1":return Ae[r];case"i8":return Ae[r];case"i16":return ye[r>>1];case"i32":return Se[r>>2];case"i64":return Se[r>>2];case"float":return Ce[r>>2];case"double":return xe[0]=Se[r>>2],xe[1]=Se[r+4>>2],ze[0];default:a("invalid type for setValue: "+e)}return null}function _(r,a,e){var i,v;"number"==typeof r?(i=!0,v=r):(i=!1,v=r.length);var f="string"==typeof a?a:null,_=[Jr,le.stackAlloc,le.staticAlloc][void 0===e?we:e](Math.max(v,f?1:a.length));if(i)return Fa(_,0,v),_;for(var s,n=0;n>12<<12}function l(){for(;Le<=Ie;)Le=o(2*Le);var r=Ae,a=new ArrayBuffer(Le);Ae=new Int8Array(a),ye=new Int16Array(a),Se=new Int32Array(a),ge=new Uint8Array(a),me=new Uint16Array(a),Me=new Uint32Array(a),Ce=new Float32Array(a),Re=new Float64Array(a),Ae.set(r)}function b(r){for(;r.length>0;){var a=r.shift(),e=a.func;"number"==typeof e&&(e=pe[e]),e(void 0===a.arg?null:a.arg)}}function k(){b(Ve)}function u(){b(Be),be.print()}function c(r,a){return Array.prototype.slice.call(Ae.subarray(r,r+a))}function h(r,a){for(var e=new Uint8Array(a),i=0;i255&&(v&=255),e.push(v),i+=1}return a||e.push(0),e}function E(r){for(var a=[],e=0;e255&&(i&=255),a.push(String.fromCharCode(i))}return a.join("")}function A(r,a,e){for(var i=0;i255&&(v&=255),Ae[a+i]=v,i+=1}e||(Ae[a+i]=0)}function g(r,a,e,i){return r>=0?r:a<=32?2*Math.abs(1<=v&&(a<=32||r>v)&&(r=-2*v+r),r}function m(r,a,e){if(0==(0|r)|0==(0|a)|0==(0|e))var i=0;else{Se[r>>2]=0,Se[r+4>>2]=a,Se[r+8>>2]=e;var i=1}var i;return i}function S(r,a,e){if(0==(0|r)|(0|a)<0|0==(0|e))var i=0;else{Se[r>>2]=41,Se[r+4>>2]=a,Se[r+8>>2]=e;var i=1}var i;return i}function M(r,a,e){if(0==(0|r)|0==(0|e))var i=0;else{Se[r>>2]=6,Se[r+4>>2]=a,Se[r+8>>2]=e;var i=1}var i;return i}function C(r,a,e){if(0==(0|r)|0==(0|e))var i=0;else{Se[r>>2]=7,Se[r+4>>2]=a,Se[r+8>>2]=e;var i=1}var i;return i}function R(r,a){var e,i=0==(0|a);do if(i)var v=0;else{var e=(r+32|0)>>2,t=Se[e];if((0|t)>=(0|Se[r+36>>2])){var v=0;break}var f=(t<<2)+Se[r+28>>2]|0;Se[f>>2]=a;var _=Se[e]+1|0;Se[e]=_;var v=1}while(0);var v;return v}function T(r,a){var e,e=(r+12|0)>>2,i=Se[e],v=i+1|0;Se[e]=v;var t=Ae[i]<<24>>24==95;do if(t){var f=i+2|0;if(Se[e]=f,Ae[v]<<24>>24!=90){var _=0;break}var s=O(r,a),_=s}else var _=0;while(0);var _;return _}function O(r,a){var e=r+12|0,i=Ae[Se[e>>2]];r:do if(i<<24>>24==71||i<<24>>24==84)var v=Tr(r),t=v;else{var f=Ar(r),_=0==(0|f)|0==(0|a);do if(!_){if(0!=(1&Se[r+8>>2]|0))break;var s=Me[f>>2],n=(s-25|0)>>>0<3;a:do if(n)for(var o=f;;){var o,l=Me[o+4>>2],b=Me[l>>2];if((b-25|0)>>>0>=3){var k=l,u=b;break a}var o=l}else var k=f,u=s;while(0);var u,k;if(2!=(0|u)){var t=k;break r}var c=k+8|0,h=Me[c>>2],d=(Se[h>>2]-25|0)>>>0<3;a:do if(d)for(var w=h;;){var w,p=Me[w+4>>2];if((Se[p>>2]-25|0)>>>0>=3){var E=p;break a}var w=p}else var E=h;while(0);var E;Se[c>>2]=E;var t=k;break r}while(0);var A=Ae[Se[e>>2]];if(A<<24>>24==0||A<<24>>24==69){var t=f;break}var g=Or(f),y=Sr(r,g),m=D(r,3,f,y),t=m}while(0);var t;return t}function N(r){var a,e,i=Oe;Oe+=4;var v=i,e=v>>2,a=(r+12|0)>>2,t=Me[a],f=Ae[t],_=f<<24>>24;r:do if(f<<24>>24==114||f<<24>>24==86||f<<24>>24==75){var s=I(r,v,0);if(0==(0|s)){var n=0;break}var o=N(r);Se[s>>2]=o;var l=Se[e],b=R(r,l);if(0==(0|b)){var n=0;break}var n=Se[e]}else{do{if(97==(0|_)||98==(0|_)||99==(0|_)||100==(0|_)||101==(0|_)||102==(0|_)||103==(0|_)||104==(0|_)||105==(0|_)||106==(0|_)||108==(0|_)||109==(0|_)||110==(0|_)||111==(0|_)||115==(0|_)||116==(0|_)||118==(0|_)||119==(0|_)||120==(0|_)||121==(0|_)||122==(0|_)){var k=ai+20*(_-97)|0,u=P(r,k);Se[e]=u;var c=r+48|0,h=Se[c>>2]+Se[Se[u+4>>2]+4>>2]|0;Se[c>>2]=h;var d=Se[a]+1|0;Se[a]=d;var n=u;break r}if(117==(0|_)){Se[a]=t+1|0;var w=L(r),p=D(r,34,w,0);Se[e]=p;var E=p}else if(70==(0|_)){var A=F(r);Se[e]=A;var E=A}else if(48==(0|_)||49==(0|_)||50==(0|_)||51==(0|_)||52==(0|_)||53==(0|_)||54==(0|_)||55==(0|_)||56==(0|_)||57==(0|_)||78==(0|_)||90==(0|_)){var g=X(r);Se[e]=g;var E=g}else if(65==(0|_)){var y=j(r);Se[e]=y;var E=y}else if(77==(0|_)){var m=U(r);Se[e]=m;var E=m}else if(84==(0|_)){var S=x(r);if(Se[e]=S,Ae[Se[a]]<<24>>24!=73){var E=S;break}var M=R(r,S);if(0==(0|M)){var n=0;break r}var C=Se[e],T=z(r),O=D(r,4,C,T);Se[e]=O;var E=O}else if(83==(0|_)){var B=ge[t+1|0];if((B-48&255&255)<10|B<<24>>24==95|(B-65&255&255)<26){var H=V(r,0);if(Se[e]=H,Ae[Se[a]]<<24>>24!=73){var n=H;break r}var K=z(r),Y=D(r,4,H,K);Se[e]=Y;var E=Y}else{var G=X(r);if(Se[e]=G,0==(0|G)){var E=0;break}if(21==(0|Se[G>>2])){var n=G;break r}var E=G}}else if(80==(0|_)){Se[a]=t+1|0;var W=N(r),Z=D(r,29,W,0);Se[e]=Z;var E=Z}else if(82==(0|_)){Se[a]=t+1|0;var Q=N(r),q=D(r,30,Q,0);Se[e]=q;var E=q}else if(67==(0|_)){Se[a]=t+1|0;var $=N(r),J=D(r,31,$,0);Se[e]=J;var E=J}else if(71==(0|_)){Se[a]=t+1|0;var rr=N(r),ar=D(r,32,rr,0);Se[e]=ar;var E=ar}else{if(85!=(0|_)){var n=0;break r}Se[a]=t+1|0;var er=L(r);Se[e]=er;var ir=N(r),vr=Se[e],tr=D(r,28,ir,vr);Se[e]=tr;var E=tr}}while(0);var E,fr=R(r,E);if(0==(0|fr)){var n=0;break}var n=Se[e]}while(0);var n;return Oe=i,n}function I(r,a,e){for(var i,v=r+12|0,t=0!=(0|e),f=t?25:22,i=(r+48|0)>>2,_=t?26:23,s=t?27:24,n=a;;){var n,o=Se[v>>2],l=Ae[o];if(l<<24>>24!=114&&l<<24>>24!=86&&l<<24>>24!=75){var b=n;break}var k=o+1|0;if(Se[v>>2]=k,l<<24>>24==114){var u=Se[i]+9|0;Se[i]=u;var c=f}else if(l<<24>>24==86){var h=Se[i]+9|0;Se[i]=h;var c=_}else{var d=Se[i]+6|0;Se[i]=d;var c=s}var c,w=D(r,c,0,0);if(Se[n>>2]=w,0==(0|w)){var b=0;break}var n=w+4|0}var b;return b}function P(r,a){var e=0==(0|a);do if(e)var i=0;else{var v=J(r);if(0==(0|v)){var i=0;break}Se[v>>2]=33,Se[v+4>>2]=a;var i=v}while(0);var i;return i}function D(r,a,e,i){var v,t;do{if(1==(0|a)||2==(0|a)||3==(0|a)||4==(0|a)||10==(0|a)||28==(0|a)||37==(0|a)||43==(0|a)||44==(0|a)||45==(0|a)||46==(0|a)||47==(0|a)||48==(0|a)||49==(0|a)||50==(0|a)){if(0==(0|e)|0==(0|i)){var f=0;t=7;break}t=5;break}if(8==(0|a)||9==(0|a)||11==(0|a)||12==(0|a)||13==(0|a)||14==(0|a)||15==(0|a)||16==(0|a)||17==(0|a)||18==(0|a)||19==(0|a)||20==(0|a)||29==(0|a)||30==(0|a)||31==(0|a)||32==(0|a)||34==(0|a)||38==(0|a)||39==(0|a)||42==(0|a)){if(0==(0|e)){var f=0;t=7;break}t=5;break}if(36==(0|a)){if(0==(0|i)){var f=0;t=7;break}t=5;break}if(35==(0|a)||22==(0|a)||23==(0|a)||24==(0|a)||25==(0|a)||26==(0|a)||27==(0|a))t=5;else{var f=0;t=7}}while(0);do if(5==t){var _=J(r),v=_>>2;if(0==(0|_)){var f=0;break}Se[v]=a,Se[v+1]=e,Se[v+2]=i;var f=_}while(0);var f;return f}function L(r){var a=sr(r);if((0|a)<1)var e=0;else{var i=Rr(r,a);Se[r+44>>2]=i;var e=i}var e;return e}function F(r){var a,a=(r+12|0)>>2,e=Se[a],i=e+1|0;if(Se[a]=i,Ae[e]<<24>>24==70){if(Ae[i]<<24>>24==89){var v=e+2|0;Se[a]=v}var t=Sr(r,1),f=Se[a],_=f+1|0;Se[a]=_;var s=Ae[f]<<24>>24==69?t:0,n=s}else var n=0;var n;return n}function X(r){var a=Ar(r);return a}function j(r){var a,a=(r+12|0)>>2,e=Se[a],i=e+1|0;Se[a]=i;var v=Ae[e]<<24>>24==65;do if(v){var t=Ae[i];if(t<<24>>24==95)var f=0;else if((t-48&255&255)<10){for(var _=i;;){var _,s=_+1|0;if(Se[a]=s,(Ae[s]-48&255&255)>=10)break;var _=s}var n=s-i|0,o=lr(r,i,n);if(0==(0|o)){var l=0;break}var f=o}else{var b=nr(r);if(0==(0|b)){var l=0;break}var f=b}var f,k=Se[a],u=k+1|0;if(Se[a]=u,Ae[k]<<24>>24!=95){var l=0;break}var c=N(r),h=D(r,36,f,c),l=h}else var l=0;while(0);var l;return l}function U(r){var a=Oe;Oe+=4;var e=a,i=r+12|0,v=Se[i>>2],t=v+1|0;Se[i>>2]=t;var f=Ae[v]<<24>>24==77;r:do if(f){var _=N(r),s=I(r,e,1);if(0==(0|s)){var n=0;break}var o=N(r);Se[s>>2]=o;var l=(0|s)==(0|e);do if(!l){if(35==(0|Se[o>>2]))break;var b=Se[e>>2],k=R(r,b);if(0==(0|k)){var n=0;break r}}while(0);var u=Se[e>>2],c=D(r,37,_,u),n=c}else var n=0;while(0);var n;return Oe=a,n}function x(r){var a,a=(r+12|0)>>2,e=Se[a],i=e+1|0;Se[a]=i;var v=Ae[e]<<24>>24==84;do if(v){if(Ae[i]<<24>>24==95)var t=0,f=i;else{var _=sr(r);if((0|_)<0){var s=0;break}var t=_+1|0,f=Se[a]}var f,t;if(Se[a]=f+1|0,Ae[f]<<24>>24!=95){var s=0;break}var n=r+40|0,o=Se[n>>2]+1|0;Se[n>>2]=o;var l=Er(r,t),s=l}else var s=0;while(0);var s;return s}function z(r){var a,e=Oe;Oe+=4;var i=e,v=r+44|0,t=Se[v>>2],a=(r+12|0)>>2,f=Se[a],_=f+1|0;Se[a]=_;var s=Ae[f]<<24>>24==73;r:do if(s){Se[i>>2]=0;for(var n=i;;){var n,o=_r(r);if(0==(0|o)){var l=0;break r}var b=D(r,39,o,0);if(Se[n>>2]=b,0==(0|b)){var l=0;break r}var k=Se[a];if(Ae[k]<<24>>24==69)break;var n=b+8|0}var u=k+1|0;Se[a]=u,Se[v>>2]=t;var l=Se[i>>2]}else var l=0;while(0);var l;return Oe=e,l}function V(r,a){var e,e=(r+12|0)>>2,i=Se[e],v=i+1|0;Se[e]=v;var t=Ae[i]<<24>>24==83;r:do if(t){var f=i+2|0;Se[e]=f;var _=ge[v];if(_<<24>>24==95)var s=0;else{if(!((_-48&255&255)<10|(_-65&255&255)<26)){var n=8&Se[r+8>>2],o=n>>>3,l=0!=(0|n)|0==(0|a);do if(l)var b=o;else{if((Ae[f]-67&255&255)>=2){var b=o;break}var b=1}while(0);for(var b,k=0|ei;;){var k;if(k>>>0>=(ei+196|0)>>>0){var u=0;break r}if(_<<24>>24==Ae[0|k]<<24>>24)break;var k=k+28|0}var c=Se[k+20>>2];if(0!=(0|c)){var h=Se[k+24>>2],d=fr(r,c,h);Se[r+44>>2]=d}if(0==(0|b))var w=k+8|0,p=k+4|0;else var w=k+16|0,p=k+12|0;var p,w,E=Se[w>>2],A=Se[p>>2],g=r+48|0,y=Se[g>>2]+E|0;Se[g>>2]=y;var m=fr(r,A,E),u=m;break}for(var S=_,M=0,C=f;;){var C,M,S;if((S-48&255&255)<10)var R=36*M-48|0;else{if((S-65&255&255)>=26){var u=0;break r}var R=36*M-55|0}var R,T=(S<<24>>24)+R|0;if((0|T)<0){var u=0;break r}var O=C+1|0;Se[e]=O;var N=ge[C];if(N<<24>>24==95)break;var S=N,M=T,C=O}var s=T+1|0}var s;if((0|s)>=(0|Se[r+32>>2])){var u=0;break}var I=r+40|0,P=Se[I>>2]+1|0;Se[I>>2]=P;var u=Se[Se[r+28>>2]+(s<<2)>>2]}else var u=0;while(0);var u;return u}function B(r,a,e,i){var v,t,f,_,s=Oe;Oe+=28;var n,o=s,_=o>>2;Se[_]=r;var l=e+1|0,f=(o+12|0)>>2;Se[f]=l;var b=Jr(l),t=(o+4|0)>>2;if(Se[t]=b,0==(0|b))var k=0,u=1;else{var v=(o+8|0)>>2;Se[v]=0,Se[_+4]=0,Se[_+5]=0;var c=o+24|0;Se[c>>2]=0,H(o,a);var h=Me[t],d=0==(0|h);do{if(!d){var w=Me[v];if(w>>>0>=Me[f]>>>0){n=5;break}Se[v]=w+1|0,Ae[h+w|0]=0,n=6;break}n=5}while(0);5==n&&Y(o,0);var p=Se[t],E=0==(0|p)?Se[c>>2]:Se[f],k=p,u=E}var u,k;return Se[i>>2]=u,Oe=s,k}function H(r,a){var e,i,v,t,f,_,s,n,o,l,b,k,u,c,h,d,w,p,E,A,g,y,m,S,M,C,R,T,O,N,I,P,D,L,F,X,j,U,x,z,V,B,K,G,W,J,vr,tr,fr,_r,sr,nr,or,lr,br,kr,ur,cr,hr,dr,wr,pr=a>>2,Er=r>>2,Ar=Oe;Oe+=184;var gr,yr=Ar,wr=yr>>2,mr=Ar+64,dr=mr>>2,Sr=Ar+72,Mr=Ar+88,Cr=Ar+104,hr=Cr>>2,Rr=Ar+168,Tr=0==(0|a);r:do if(Tr)Z(r);else{var cr=(r+4|0)>>2,Or=Me[cr];if(0==(0|Or))break;var Nr=0|a,Ir=Me[Nr>>2];a:do{if(0==(0|Ir)){if(0!=(4&Se[Er]|0)){var Pr=Se[pr+1],Dr=Se[pr+2];q(r,Pr,Dr);break r}var ur=(r+8|0)>>2,Lr=Me[ur],Fr=a+8|0,Xr=Me[Fr>>2];if((Xr+Lr|0)>>>0>Me[Er+3]>>>0){var jr=Se[pr+1];Q(r,jr,Xr);break r}var Ur=Or+Lr|0,xr=Se[pr+1];Pa(Ur,xr,Xr,1);var zr=Se[ur]+Se[Fr>>2]|0;Se[ur]=zr;break r}if(1==(0|Ir)||2==(0|Ir)){var Vr=Se[pr+1];H(r,Vr);var Br=0==(4&Se[Er]|0),Hr=Me[cr],Kr=0!=(0|Hr);e:do if(Br){do if(Kr){var kr=(r+8|0)>>2,Yr=Me[kr];if((Yr+2|0)>>>0>Me[Er+3]>>>0)break;var Gr=Hr+Yr|0;oe=14906,Ae[Gr]=255&oe,oe>>=8,Ae[Gr+1]=255&oe;var Wr=Se[kr]+2|0;Se[kr]=Wr;break e}while(0);Q(r,0|He.__str120,2)}else{do if(Kr){var Zr=r+8|0,Qr=Me[Zr>>2];if(Qr>>>0>=Me[Er+3]>>>0)break;Se[Zr>>2]=Qr+1|0,Ae[Hr+Qr|0]=46;break e}while(0);Y(r,46)}while(0);var qr=Se[pr+2];H(r,qr);break r}if(3==(0|Ir)){for(var br=(r+20|0)>>2,$r=Me[br],lr=(r+16|0)>>2,Jr=a,ra=0,aa=$r;;){var aa,ra,Jr,ea=Me[Jr+4>>2];if(0==(0|ea)){var ia=ra,va=0;gr=33;break}if(ra>>>0>3){Z(r);break r}var ta=(ra<<4)+yr|0;Se[ta>>2]=aa,Se[br]=ta,Se[((ra<<4)+4>>2)+wr]=ea,Se[((ra<<4)+8>>2)+wr]=0;var fa=Me[lr];Se[((ra<<4)+12>>2)+wr]=fa;var _a=ra+1|0,sa=0|ea,na=Me[sa>>2];if((na-25|0)>>>0>=3){gr=25;break}var Jr=ea,ra=_a,aa=ta}e:do if(25==gr){if(4==(0|na)){Se[dr]=fa,Se[lr]=mr,Se[dr+1]=ea;var oa=Se[sa>>2],la=mr}else var oa=na,la=fa;var la,oa;if(2!=(0|oa)){var ia=_a,va=sa;break}for(var ba=_a,ka=ea+8|0;;){var ka,ba,ua=Me[ka>>2];if((Se[ua>>2]-25|0)>>>0>=3){var ia=ba,va=sa;break e}if(ba>>>0>3)break;var ca=(ba<<4)+yr|0,ha=ba-1|0,da=(ha<<4)+yr|0,or=ca>>2,nr=da>>2;Se[or]=Se[nr],Se[or+1]=Se[nr+1],Se[or+2]=Se[nr+2],Se[or+3]=Se[nr+3],Se[ca>>2]=da,Se[br]=ca,Se[((ha<<4)+4>>2)+wr]=ua,Se[((ha<<4)+8>>2)+wr]=0,Se[((ha<<4)+12>>2)+wr]=la;var ba=ba+1|0,ka=ua+4|0}Z(r);break r}while(0);var va,ia,wa=Se[pr+2];if(H(r,wa),4==(0|Se[va>>2])){var pa=Se[dr];Se[lr]=pa}var Ea=0==(0|ia);e:do if(!Ea)for(var Aa=r+8|0,ga=r+12|0,ya=ia;;){var ya,ma=ya-1|0;if(0==(0|Se[((ma<<4)+8>>2)+wr])){var Sa=Me[cr],Ma=0==(0|Sa);do{if(!Ma){var Ca=Me[Aa>>2];if(Ca>>>0>=Me[ga>>2]>>>0){gr=41;break}Se[Aa>>2]=Ca+1|0,Ae[Sa+Ca|0]=32,gr=42;break}gr=41}while(0);41==gr&&Y(r,32);var Ra=Se[((ma<<4)+4>>2)+wr];$(r,Ra)}if(0==(0|ma))break e;var ya=ma}while(0);Se[br]=$r;break r}if(4==(0|Ir)){var sr=(r+20|0)>>2,Ta=Se[sr];Se[sr]=0;var Oa=Se[pr+1];H(r,Oa);var Na=Me[cr],Ia=0==(0|Na);do{if(!Ia){var _r=(r+8|0)>>2,Da=Me[_r],La=0==(0|Da);do if(!La){if(Ae[Na+(Da-1)|0]<<24>>24!=60)break;Da>>>0>>0?(Se[_r]=Da+1|0,Ae[Na+Da|0]=32):Y(r,32)}while(0);var Fa=Me[cr];if(0==(0|Fa)){gr=54;break}var Xa=Me[_r];if(Xa>>>0>=Me[Er+3]>>>0){gr=54;break}Se[_r]=Xa+1|0,Ae[Fa+Xa|0]=60,gr=55;break}gr=54}while(0);54==gr&&Y(r,60);var ja=Se[pr+2];H(r,ja);var Ua=Me[cr],xa=0==(0|Ua);do{if(!xa){var fr=(r+8|0)>>2,za=Me[fr],Va=0==(0|za);do if(!Va){if(Ae[Ua+(za-1)|0]<<24>>24!=62)break;za>>>0>>0?(Se[fr]=za+1|0,Ae[Ua+za|0]=32):Y(r,32)}while(0);var Ba=Me[cr];if(0==(0|Ba)){gr=64;break}var Ha=Me[fr];if(Ha>>>0>=Me[Er+3]>>>0){gr=64;break}Se[fr]=Ha+1|0,Ae[Ba+Ha|0]=62,gr=65;break}gr=64}while(0);64==gr&&Y(r,62),Se[sr]=Ta;break r}if(5==(0|Ir)){var tr=(r+16|0)>>2,Ka=Me[tr];if(0==(0|Ka)){Z(r);break r}for(var Ya=Se[pr+1],Ga=Se[Ka+4>>2];;){var Ga,Ya,Wa=Se[Ga+8>>2];if(0==(0|Wa))break;if(39!=(0|Se[Wa>>2])){Z(r);break r}if((0|Ya)<1){if(0!=(0|Ya))break;var Za=Se[Ka>>2];Se[tr]=Za;var Qa=Se[Wa+4>>2];H(r,Qa),Se[tr]=Ka;break r}var Ya=Ya-1|0,Ga=Wa}Z(r);break r}if(6==(0|Ir)){var qa=Se[pr+2];H(r,qa);break r}if(7==(0|Ir)){var $a=r+8|0,Ja=Me[$a>>2];Ja>>>0>>0?(Se[$a>>2]=Ja+1|0,Ae[Or+Ja|0]=126):Y(r,126);var re=Se[pr+2];H(r,re);break r}if(8==(0|Ir)){var vr=(r+8|0)>>2,ae=Me[vr];if((ae+11|0)>>>0>Me[Er+3]>>>0)Q(r,0|He.__str121,11);else{for(var ee=Or+ae|0,ie=0|He.__str121,ve=ee,te=ie+11;ie>2,se=Me[J];if((se+8|0)>>>0>Me[Er+3]>>>0)Q(r,0|He.__str122,8);else{var ne=Or+se|0,le=0|ne;oe=542397526,Ae[le]=255&oe,oe>>=8,Ae[le+1]=255&oe,oe>>=8,Ae[le+2]=255&oe,oe>>=8,Ae[le+3]=255&oe;var be=ne+4|0;oe=544370534,Ae[be]=255&oe,oe>>=8,Ae[be+1]=255&oe,oe>>=8,Ae[be+2]=255&oe,oe>>=8,Ae[be+3]=255&oe;var ke=Se[J]+8|0;Se[J]=ke}var ue=Se[pr+1];H(r,ue);break r}if(10==(0|Ir)){var W=(r+8|0)>>2,ce=Me[W],he=r+12|0;if((ce+24|0)>>>0>Me[he>>2]>>>0)Q(r,0|He.__str123,24);else{var de=Or+ce|0;Pa(de,0|He.__str123,24,1);var we=Se[W]+24|0;Se[W]=we}var pe=Se[pr+1];H(r,pe);var Ee=Me[cr],ge=0==(0|Ee);do{if(!ge){var ye=Me[W];if((ye+4|0)>>>0>Me[he>>2]>>>0){gr=96;break}var me=Ee+ye|0;oe=762210605,Ae[me]=255&oe,oe>>=8,Ae[me+1]=255&oe,oe>>=8,Ae[me+2]=255&oe,oe>>=8,Ae[me+3]=255&oe;var Ce=Se[W]+4|0;Se[W]=Ce,gr=97;break}gr=96}while(0);96==gr&&Q(r,0|He.__str124,4);var Re=Se[pr+2];H(r,Re);break r}if(11==(0|Ir)){var G=(r+8|0)>>2,Te=Me[G];if((Te+13|0)>>>0>Me[Er+3]>>>0)Q(r,0|He.__str125,13);else{for(var Ne=Or+Te|0,ie=0|He.__str125,ve=Ne,te=ie+13;ie>2,De=Me[K];if((De+18|0)>>>0>Me[Er+3]>>>0)Q(r,0|He.__str126,18);else{for(var Le=Or+De|0,ie=0|He.__str126,ve=Le,te=ie+18;ie>2,je=Me[B];if((je+16|0)>>>0>Me[Er+3]>>>0)Q(r,0|He.__str127,16);else{for(var Ue=Or+je|0,ie=0|He.__str127,ve=Ue,te=ie+16;ie>2,Ve=Me[V];if((Ve+21|0)>>>0>Me[Er+3]>>>0)Q(r,0|He.__str128,21);else{var Be=Or+Ve|0;Pa(Be,0|He.__str128,21,1);var Ke=Se[V]+21|0;Se[V]=Ke}var Ye=Se[pr+1];H(r,Ye);break r}if(15==(0|Ir)){var z=(r+8|0)>>2,Ge=Me[z];if((Ge+17|0)>>>0>Me[Er+3]>>>0)Q(r,0|He.__str129,17);else{for(var We=Or+Ge|0,ie=0|He.__str129,ve=We,te=ie+17;ie>2,qe=Me[x];if((qe+26|0)>>>0>Me[Er+3]>>>0)Q(r,0|He.__str130,26);else{var $e=Or+qe|0;Pa($e,0|He.__str130,26,1);var Je=Se[x]+26|0;Se[x]=Je}var ri=Se[pr+1];H(r,ri);break r}if(17==(0|Ir)){var U=(r+8|0)>>2,ai=Me[U];if((ai+15|0)>>>0>Me[Er+3]>>>0)Q(r,0|He.__str131,15);else{for(var ei=Or+ai|0,ie=0|He.__str131,ve=ei,te=ie+15;ie>2,ti=Me[j];if((ti+19|0)>>>0>Me[Er+3]>>>0)Q(r,0|He.__str132,19);else{for(var fi=Or+ti|0,ie=0|He.__str132,ve=fi,te=ie+19;ie>2,ni=Me[X];if((ni+24|0)>>>0>Me[Er+3]>>>0)Q(r,0|He.__str133,24);else{var oi=Or+ni|0;Pa(oi,0|He.__str133,24,1);var li=Se[X]+24|0;Se[X]=li}var bi=Se[pr+1];H(r,bi);break r}if(20==(0|Ir)){var F=(r+8|0)>>2,ki=Me[F];if((ki+17|0)>>>0>Me[Er+3]>>>0)Q(r,0|He.__str134,17);else{for(var ui=Or+ki|0,ie=0|He.__str134,ve=ui,te=ie+17;ie>2,di=Me[L],wi=a+8|0,pi=Me[wi>>2];if((pi+di|0)>>>0>Me[Er+3]>>>0){var Ei=Se[pr+1];Q(r,Ei,pi);break r}var Ai=Or+di|0,gi=Se[pr+1];Pa(Ai,gi,pi,1);var yi=Se[L]+Se[wi>>2]|0;Se[L]=yi;break r}if(22==(0|Ir)||23==(0|Ir)||24==(0|Ir)){for(var mi=r+20|0;;){var mi,Si=Me[mi>>2];if(0==(0|Si))break a;if(0==(0|Se[Si+8>>2])){var Mi=Me[Se[Si+4>>2]>>2];if((Mi-22|0)>>>0>=3)break a;if((0|Mi)==(0|Ir))break}var mi=0|Si}var Ci=Se[pr+1];H(r,Ci);break r}if(25!=(0|Ir)&&26!=(0|Ir)&&27!=(0|Ir)&&28!=(0|Ir)&&29!=(0|Ir)&&30!=(0|Ir)&&31!=(0|Ir)&&32!=(0|Ir)){if(33==(0|Ir)){var D=(r+8|0)>>2,Ri=Me[D],P=(a+4|0)>>2,I=Me[P]>>2;if(0==(4&Se[Er]|0)){var Ti=Me[I+1];if((Ti+Ri|0)>>>0>Me[Er+3]>>>0){var Oi=Se[I];Q(r,Oi,Ti);break r}var Ni=Or+Ri|0,Ii=Se[I];Pa(Ni,Ii,Ti,1);var Pi=Se[D]+Se[Se[P]+4>>2]|0;Se[D]=Pi;break r}var Di=Me[I+3];if((Di+Ri|0)>>>0>Me[Er+3]>>>0){var Li=Se[I+2];Q(r,Li,Di);break r}var Fi=Or+Ri|0,Xi=Se[I+2];Pa(Fi,Xi,Di,1);var ji=Se[D]+Se[Se[P]+12>>2]|0;Se[D]=ji;break r}if(34==(0|Ir)){var Ui=Se[pr+1];H(r,Ui);break r}if(35==(0|Ir)){var N=(0|r)>>2;if(0!=(32&Se[N]|0)){var xi=Se[Er+5];rr(r,a,xi)}var zi=a+4|0,Vi=0==(0|Se[zi>>2]);e:do if(!Vi){var O=(r+20|0)>>2,Bi=Se[O],Hi=0|Mr;Se[Hi>>2]=Bi,Se[O]=Mr,Se[Mr+4>>2]=a;var Ki=Mr+8|0;Se[Ki>>2]=0;var Yi=Se[Er+4];Se[Mr+12>>2]=Yi;var Gi=Se[zi>>2];H(r,Gi);var Wi=Se[Hi>>2];if(Se[O]=Wi,0!=(0|Se[Ki>>2]))break r;if(0!=(32&Se[N]|0))break;var Zi=Me[cr],Qi=0==(0|Zi);do if(!Qi){var qi=r+8|0,$i=Me[qi>>2];if($i>>>0>=Me[Er+3]>>>0)break;Se[qi>>2]=$i+1|0,Ae[Zi+$i|0]=32;break e}while(0);Y(r,32)}while(0);if(0!=(32&Se[N]|0))break r;var Ji=Se[Er+5];rr(r,a,Ji);break r}if(36==(0|Ir)){var T=(r+20|0)>>2,rv=Me[T],av=0|Cr;Se[hr]=rv,Se[T]=av,Se[hr+1]=a;var ev=Cr+8|0;Se[ev>>2]=0;var iv=Se[Er+4];Se[hr+3]=iv;for(var vv=rv,tv=1;;){var tv,vv;if(0==(0|vv))break;if((Se[Se[vv+4>>2]>>2]-22|0)>>>0>=3)break;var fv=vv+8|0;if(0==(0|Se[fv>>2])){if(tv>>>0>3){Z(r);break r}var _v=(tv<<4)+Cr|0,R=_v>>2,C=vv>>2;Se[R]=Se[C],Se[R+1]=Se[C+1],Se[R+2]=Se[C+2],Se[R+3]=Se[C+3];var sv=Se[T];Se[_v>>2]=sv,Se[T]=_v,Se[fv>>2]=1;var nv=tv+1|0}else var nv=tv;var nv,vv=Se[vv>>2],tv=nv}var ov=Se[pr+2];if(H(r,ov),Se[T]=rv,0!=(0|Se[ev>>2]))break r;if(tv>>>0>1){for(var lv=tv;;){var lv,bv=lv-1|0,kv=Se[((bv<<4)+4>>2)+hr];if($(r,kv),bv>>>0<=1)break;var lv=bv}var uv=Se[T]}else var uv=rv;var uv;ar(r,a,uv);break r}if(37==(0|Ir)){var M=(r+20|0)>>2,cv=Se[M],hv=0|Rr;Se[hv>>2]=cv,Se[M]=Rr,Se[Rr+4>>2]=a;var dv=Rr+8|0;Se[dv>>2]=0;var wv=Se[Er+4];Se[Rr+12>>2]=wv;var pv=a+4|0,Ev=Se[pr+2];H(r,Ev);var Av=0==(0|Se[dv>>2]);e:do if(Av){var gv=Me[cr],yv=0==(0|gv);do{if(!yv){var mv=r+8|0,Sv=Me[mv>>2];if(Sv>>>0>=Me[Er+3]>>>0){gr=187;break}Se[mv>>2]=Sv+1|0,Ae[gv+Sv|0]=32,gr=188;break}gr=187}while(0);187==gr&&Y(r,32);var Mv=Se[pv>>2];H(r,Mv);var Cv=Me[cr],Rv=0==(0|Cv);do if(!Rv){var S=(r+8|0)>>2,Tv=Me[S];if((Tv+3|0)>>>0>Me[Er+3]>>>0)break;var Ov=Cv+Tv|0;Ae[Ov]=Ae[0|He.__str135],Ae[Ov+1]=Ae[(0|He.__str135)+1],Ae[Ov+2]=Ae[(0|He.__str135)+2];var Nv=Se[S]+3|0;Se[S]=Nv;break e}while(0);Q(r,0|He.__str135,3)}while(0);var Iv=Se[hv>>2];Se[M]=Iv;break r}if(38==(0|Ir)||39==(0|Ir)){var Pv=Se[pr+1];H(r,Pv);var Dv=a+8|0;if(0==(0|Se[Dv>>2]))break r;var Lv=Me[cr],Fv=0==(0|Lv);do{if(!Fv){var m=(r+8|0)>>2,Xv=Me[m];if((Xv+2|0)>>>0>Me[Er+3]>>>0){gr=197;break}var jv=Lv+Xv|0;oe=8236,Ae[jv]=255&oe,oe>>=8,Ae[jv+1]=255&oe;var Uv=Se[m]+2|0;Se[m]=Uv,gr=198;break}gr=197}while(0);197==gr&&Q(r,0|He.__str136,2);var xv=Se[Dv>>2];H(r,xv);break r}if(40==(0|Ir)){var y=(r+8|0)>>2,zv=Me[y],g=(r+12|0)>>2;if((zv+8|0)>>>0>Me[g]>>>0)Q(r,0|He.__str137,8);else{var Vv=Or+zv|0,le=0|Vv;oe=1919250543,Ae[le]=255&oe,oe>>=8,Ae[le+1]=255&oe,oe>>=8,Ae[le+2]=255&oe,oe>>=8,Ae[le+3]=255&oe;var be=Vv+4|0;oe=1919906913,Ae[be]=255&oe,oe>>=8,Ae[be+1]=255&oe,oe>>=8,Ae[be+2]=255&oe,oe>>=8,Ae[be+3]=255&oe;var Bv=Se[y]+8|0;Se[y]=Bv}var A=(a+4|0)>>2,Hv=(Ae[Se[Se[A]+4>>2]]-97&255&255)<26;e:do if(Hv){var Kv=Me[cr],Yv=0==(0|Kv);do if(!Yv){var Gv=Me[y];if(Gv>>>0>=Me[g]>>>0)break;Se[y]=Gv+1|0,Ae[Kv+Gv|0]=32;break e}while(0);Y(r,32)}while(0);var Wv=Me[cr],Zv=0==(0|Wv);do{if(!Zv){var Qv=Me[y],qv=Me[A],$v=Me[qv+8>>2];if(($v+Qv|0)>>>0>Me[g]>>>0){var Jv=qv,rt=$v;break}var at=Wv+Qv|0,et=Se[qv+4>>2];Pa(at,et,$v,1);var it=Se[y]+Se[Se[A]+8>>2]|0;Se[y]=it;break r}var vt=Me[A],Jv=vt,rt=Se[vt+8>>2]}while(0);var rt,Jv,tt=Se[Jv+4>>2];Q(r,tt,rt);break r}if(41==(0|Ir)){var E=(r+8|0)>>2,ft=Me[E];if((ft+9|0)>>>0>Me[Er+3]>>>0)Q(r,0|He.__str10180,9);else{for(var _t=Or+ft|0,ie=0|He.__str10180,ve=_t,te=ie+9;ie>2,ot=Me[p];if((ot+9|0)>>>0>Me[Er+3]>>>0)Q(r,0|He.__str10180,9);else{for(var lt=Or+ot|0,ie=0|He.__str10180,ve=lt,te=ie+9;ie>2],ct=42==(0|Se[ut>>2]);e:do if(ct){var w=(r+8|0)>>2,ht=Me[w],dt=r+12|0;ht>>>0>2]>>>0?(Se[w]=ht+1|0,Ae[Or+ht|0]=40):Y(r,40);var wt=Se[kt>>2];er(r,wt);var pt=Me[cr],Et=0==(0|pt);do if(!Et){var At=Me[w];if(At>>>0>=Me[dt>>2]>>>0)break;Se[w]=At+1|0,Ae[pt+At|0]=41;break e}while(0);Y(r,41)}else ir(r,ut);while(0);var gt=Me[cr],yt=0==(0|gt);do{if(!yt){var mt=r+8|0,St=Me[mt>>2];if(St>>>0>=Me[Er+3]>>>0){gr=232;break}Se[mt>>2]=St+1|0,Ae[gt+St|0]=40,gr=233;break}gr=232}while(0);232==gr&&Y(r,40);var Mt=Se[pr+2];H(r,Mt);var Ct=Me[cr],Rt=0==(0|Ct);do if(!Rt){var Tt=r+8|0,Ot=Me[Tt>>2];if(Ot>>>0>=Me[Er+3]>>>0)break;Se[Tt>>2]=Ot+1|0,Ae[Ct+Ot|0]=41;break r}while(0);Y(r,41);break r}if(44==(0|Ir)){var d=(a+8|0)>>2;if(45==(0|Se[Se[d]>>2])){var h=(a+4|0)>>2,Nt=Se[h],It=40==(0|Se[Nt>>2]);do if(It){var Pt=Se[Nt+4>>2];if(1!=(0|Se[Pt+8>>2]))break;if(Ae[Se[Pt+4>>2]]<<24>>24!=62)break;var Dt=r+8|0,Lt=Me[Dt>>2];Lt>>>0>>0?(Se[Dt>>2]=Lt+1|0,Ae[Or+Lt|0]=40):Y(r,40)}while(0);var Ft=Me[cr],Xt=0==(0|Ft);do{if(!Xt){var jt=r+8|0,Ut=Me[jt>>2];if(Ut>>>0>=Me[Er+3]>>>0){gr=248;break}Se[jt>>2]=Ut+1|0,Ae[Ft+Ut|0]=40,gr=249;break}gr=248}while(0);248==gr&&Y(r,40);var xt=Se[Se[d]+4>>2];H(r,xt);var zt=Me[cr],Vt=0==(0|zt);do{if(!Vt){var c=(r+8|0)>>2,Bt=Me[c];if((Bt+2|0)>>>0>Me[Er+3]>>>0){gr=252;break}var Ht=zt+Bt|0;oe=8233,Ae[Ht]=255&oe,oe>>=8,Ae[Ht+1]=255&oe;var Kt=Se[c]+2|0;Se[c]=Kt,gr=253;break}gr=252}while(0);252==gr&&Q(r,0|He.__str139,2);var Yt=Se[h];ir(r,Yt);var Gt=Me[cr],Wt=0==(0|Gt);do{if(!Wt){var u=(r+8|0)>>2,Zt=Me[u];if((Zt+2|0)>>>0>Me[Er+3]>>>0){gr=256;break}var Qt=Gt+Zt|0;oe=10272,Ae[Qt]=255&oe,oe>>=8,Ae[Qt+1]=255&oe;var qt=Se[u]+2|0;Se[u]=qt,gr=257;break}gr=256}while(0);256==gr&&Q(r,0|He.__str140,2);var $t=Se[Se[d]+8>>2];H(r,$t);var Jt=Me[cr],rf=0==(0|Jt);do{if(!rf){var af=r+8|0,ef=Me[af>>2];if(ef>>>0>=Me[Er+3]>>>0){gr=260;break}Se[af>>2]=ef+1|0,Ae[Jt+ef|0]=41,gr=261;break}gr=260}while(0);260==gr&&Y(r,41);var vf=Se[h];if(40!=(0|Se[vf>>2]))break r;var tf=Se[vf+4>>2];if(1!=(0|Se[tf+8>>2]))break r;if(Ae[Se[tf+4>>2]]<<24>>24!=62)break r;var ff=Me[cr],_f=0==(0|ff);do if(!_f){var sf=r+8|0,nf=Me[sf>>2];if(nf>>>0>=Me[Er+3]>>>0)break;Se[sf>>2]=nf+1|0,Ae[ff+nf|0]=41;break r}while(0);Y(r,41);break r}Z(r);break r}if(45==(0|Ir)){Z(r);break r}if(46==(0|Ir)){var of=a+4|0,k=(a+8|0)>>2,lf=Se[k],bf=47==(0|Se[lf>>2]);do if(bf){if(48!=(0|Se[Se[lf+8>>2]>>2]))break;var b=(r+8|0)>>2,kf=Me[b],l=(r+12|0)>>2;kf>>>0>>0?(Se[b]=kf+1|0,Ae[Or+kf|0]=40):Y(r,40);var uf=Se[Se[k]+4>>2];H(r,uf);var cf=Me[cr],hf=0==(0|cf);do{if(!hf){var df=Me[b];if((df+2|0)>>>0>Me[l]>>>0){gr=278;break}var wf=cf+df|0;oe=8233,Ae[wf]=255&oe,oe>>=8,Ae[wf+1]=255&oe;var pf=Se[b]+2|0;Se[b]=pf,gr=279;break}gr=278}while(0);278==gr&&Q(r,0|He.__str139,2);var Ef=Se[of>>2];ir(r,Ef);var Af=Me[cr],gf=0==(0|Af);do{if(!gf){var yf=Me[b];if((yf+2|0)>>>0>Me[l]>>>0){gr=282;break}var mf=Af+yf|0;oe=10272,Ae[mf]=255&oe,oe>>=8,Ae[mf+1]=255&oe;var Sf=Se[b]+2|0;Se[b]=Sf,gr=283;break}gr=282}while(0);282==gr&&Q(r,0|He.__str140,2);var Mf=Se[Se[Se[k]+8>>2]+4>>2];H(r,Mf);var Cf=Me[cr],Rf=0==(0|Cf);do{if(!Rf){var Tf=Me[b];if((Tf+5|0)>>>0>Me[l]>>>0){gr=286;break}var Of=Cf+Tf|0;Ae[Of]=Ae[0|He.__str141],Ae[Of+1]=Ae[(0|He.__str141)+1],Ae[Of+2]=Ae[(0|He.__str141)+2],Ae[Of+3]=Ae[(0|He.__str141)+3],Ae[Of+4]=Ae[(0|He.__str141)+4];var Nf=Se[b]+5|0;Se[b]=Nf,gr=287;break}gr=286}while(0);286==gr&&Q(r,0|He.__str141,5);var If=Se[Se[Se[k]+8>>2]+8>>2];H(r,If);var Pf=Me[cr],Df=0==(0|Pf);do if(!Df){var Lf=Me[b];if(Lf>>>0>=Me[l]>>>0)break;Se[b]=Lf+1|0,Ae[Pf+Lf|0]=41;break r}while(0);Y(r,41);break r}while(0);Z(r);break r}if(47==(0|Ir)||48==(0|Ir)){Z(r);break r}if(49==(0|Ir)||50==(0|Ir)){var Ff=a+4|0,Xf=Se[Ff>>2],jf=33==(0|Se[Xf>>2]);do{if(jf){var Uf=Me[Se[Xf+4>>2]+16>>2];if(1==(0|Uf)||2==(0|Uf)||3==(0|Uf)||4==(0|Uf)||5==(0|Uf)||6==(0|Uf)){var xf=a+8|0;if(0!=(0|Se[Se[xf>>2]>>2])){var zf=Uf;break}if(50==(0|Ir)){var Vf=r+8|0,Bf=Me[Vf>>2];Bf>>>0>>0?(Se[Vf>>2]=Bf+1|0,Ae[Or+Bf|0]=45):Y(r,45)}var Hf=Se[xf>>2];if(H(r,Hf),2==(0|Uf)){var Kf=Me[cr],Yf=0==(0|Kf);do if(!Yf){var Gf=r+8|0,Wf=Me[Gf>>2];if(Wf>>>0>=Me[Er+3]>>>0)break;Se[Gf>>2]=Wf+1|0,Ae[Kf+Wf|0]=117;break r}while(0);Y(r,117);break r}if(3==(0|Uf)){var Zf=Me[cr],Qf=0==(0|Zf);do if(!Qf){var qf=r+8|0,$f=Me[qf>>2];if($f>>>0>=Me[Er+3]>>>0)break;Se[qf>>2]=$f+1|0,Ae[Zf+$f|0]=108;break r}while(0);Y(r,108);break r}if(4==(0|Uf)){var Jf=Me[cr],r_=0==(0|Jf);do if(!r_){var o=(r+8|0)>>2,a_=Me[o];if((a_+2|0)>>>0>Me[Er+3]>>>0)break;var e_=Jf+a_|0;oe=27765,Ae[e_]=255&oe,oe>>=8,Ae[e_+1]=255&oe;var i_=Se[o]+2|0;Se[o]=i_;break r}while(0);Q(r,0|He.__str142,2);break r}if(5==(0|Uf)){var v_=Me[cr],t_=0==(0|v_);do if(!t_){var n=(r+8|0)>>2,f_=Me[n];if((f_+2|0)>>>0>Me[Er+3]>>>0)break;var __=v_+f_|0;oe=27756,Ae[__]=255&oe,oe>>=8,Ae[__+1]=255&oe;var s_=Se[n]+2|0;Se[n]=s_;break r}while(0);Q(r,0|He.__str143,2);break r}if(6==(0|Uf)){var n_=Me[cr],o_=0==(0|n_);do if(!o_){var s=(r+8|0)>>2,l_=Me[s];if((l_+3|0)>>>0>Me[Er+3]>>>0)break;var b_=n_+l_|0;Ae[b_]=Ae[0|He.__str144],Ae[b_+1]=Ae[(0|He.__str144)+1],Ae[b_+2]=Ae[(0|He.__str144)+2];var k_=Se[s]+3|0;Se[s]=k_;break r}while(0);Q(r,0|He.__str144,3);break r}break r}if(7==(0|Uf)){var _=Se[pr+2]>>2;if(0!=(0|Se[_])){var zf=7;break}if(!(1==(0|Se[_+2])&49==(0|Ir))){var zf=Uf;break}var u_=Ae[Se[_+1]]<<24>>24;if(48==(0|u_)){var f=(r+8|0)>>2,c_=Me[f];if((c_+5|0)>>>0>Me[Er+3]>>>0){Q(r,0|He.__str145,5);break r}var h_=Or+c_|0;Ae[h_]=Ae[0|He.__str145],Ae[h_+1]=Ae[(0|He.__str145)+1],Ae[h_+2]=Ae[(0|He.__str145)+2],Ae[h_+3]=Ae[(0|He.__str145)+3],Ae[h_+4]=Ae[(0|He.__str145)+4];var d_=Se[f]+5|0;Se[f]=d_;break r}if(49==(0|u_)){var t=(r+8|0)>>2,w_=Me[t];if((w_+4|0)>>>0>Me[Er+3]>>>0){Q(r,0|He.__str146,4);break r}var p_=Or+w_|0;oe=1702195828,Ae[p_]=255&oe,oe>>=8,Ae[p_+1]=255&oe,oe>>=8,Ae[p_+2]=255&oe,oe>>=8,Ae[p_+3]=255&oe;var E_=Se[t]+4|0;Se[t]=E_;break r}var zf=Uf;break}var zf=Uf;break}var zf=0}while(0);var zf,v=(r+8|0)>>2,A_=Me[v],i=(r+12|0)>>2;A_>>>0>>0?(Se[v]=A_+1|0,Ae[Or+A_|0]=40):Y(r,40);var g_=Se[Ff>>2];H(r,g_);var y_=Me[cr],m_=0==(0|y_);do{if(!m_){var S_=Me[v];if(S_>>>0>=Me[i]>>>0){gr=335;break}Se[v]=S_+1|0,Ae[y_+S_|0]=41,gr=336;break}gr=335}while(0);335==gr&&Y(r,41);var M_=50==(0|Se[Nr>>2]);e:do if(M_){var C_=Me[cr],R_=0==(0|C_);do if(!R_){var T_=Me[v];if(T_>>>0>=Me[i]>>>0)break;Se[v]=T_+1|0,Ae[C_+T_|0]=45;break e}while(0);Y(r,45)}while(0);if(8==(0|zf)){var O_=Me[cr],N_=0==(0|O_);do{if(!N_){var I_=Me[v];if(I_>>>0>=Me[i]>>>0){gr=345;break}Se[v]=I_+1|0,Ae[O_+I_|0]=91,gr=346;break}gr=345}while(0);345==gr&&Y(r,91);var P_=Se[pr+2];H(r,P_);var D_=Me[cr],L_=0==(0|D_);do if(!L_){var F_=Me[v];if(F_>>>0>=Me[i]>>>0)break;Se[v]=F_+1|0,Ae[D_+F_|0]=93;break r}while(0);Y(r,93);break r}var X_=Se[pr+2];H(r,X_);break r}Z(r);break r}}while(0);var e=(r+20|0)>>2,j_=Se[e],U_=0|Sr;Se[U_>>2]=j_,Se[e]=Sr,Se[Sr+4>>2]=a;var x_=Sr+8|0;Se[x_>>2]=0;var z_=Se[Er+4];Se[Sr+12>>2]=z_;var V_=Se[pr+1];H(r,V_),0==(0|Se[x_>>2])&&$(r,a);var B_=Se[U_>>2];Se[e]=B_}while(0);Oe=Ar}function K(r,a,e,i){var v=i>>2;Se[v]=r,Se[v+1]=r+e|0,Se[v+2]=a,Se[v+3]=r,Se[v+6]=e<<1,Se[v+5]=0,Se[v+9]=e,Se[v+8]=0,Se[v+10]=0,Se[v+11]=0,Se[v+12]=0}function Y(r,a){var e,i=r+4|0,v=Me[i>>2],t=0==(0|v);do if(!t){var e=(r+8|0)>>2,f=Me[e];if(f>>>0>2]>>>0)var _=v,s=f;else{tr(r,1);var n=Me[i>>2];if(0==(0|n))break;var _=n,s=Se[e]}var s,_;Ae[_+s|0]=255&a;var o=Se[e]+1|0;Se[e]=o}while(0)}function G(r,a,e,i){var v,t=i>>2,f=Oe;Oe+=4;var _=f,v=_>>2,s=0==(0|r);do if(s){if(0==(0|i)){var n=0;break}Se[t]=-3;var n=0}else{var o=0==(0|e);if(0!=(0|a)&o){if(0==(0|i)){var n=0;break}Se[t]=-3;var n=0}else{var l=W(r,_);if(0==(0|l)){if(0==(0|i)){var n=0;break}if(1==(0|Se[v])){Se[t]=-1;var n=0}else{Se[t]=-2;var n=0}}else{var b=0==(0|a);do if(b){if(o){var k=l;break}var u=Se[v];Se[e>>2]=u;var k=l}else{var c=Ca(l);if(c>>>0>2]>>>0){Ra(a,l);va(l);var k=a}else{va(a);var h=Se[v];Se[e>>2]=h;var k=l}}while(0);var k;if(0==(0|i)){var n=k;break}Se[t]=0;var n=k}}}while(0);var n;return Oe=f,n}function W(r,a){var e,i=Oe;Oe+=52;var v,t=i,e=t>>2;Se[a>>2]=0;var f=Ca(r),_=Ae[r]<<24>>24==95;do{if(_){if(Ae[r+1|0]<<24>>24==90){var s=0;v=13;break}v=3;break}v=3}while(0);do if(3==v){var n=Na(r,0|He.__str117,8);if(0!=(0|n)){var s=1;v=13;break}var o=Ae[r+8|0];if(o<<24>>24!=46&&o<<24>>24!=95&&o<<24>>24!=36){var s=1;v=13;break}var l=r+9|0,b=Ae[l];if(b<<24>>24!=68&&b<<24>>24!=73){ -var s=1;v=13;break}if(Ae[r+10|0]<<24>>24!=95){var s=1;v=13;break}var k=f+29|0,u=Jr(k);if(0==(0|u)){Se[a>>2]=1;var c=0;v=19;break}Ae[l]<<24>>24==73?Pa(u,0|He.__str118,30,1):Pa(u,0|He.__str119,29,1);var h=r+11|0,c=(Ia(u,h),u);v=19;break}while(0);if(13==v){var s;K(r,17,f,t);var d=Se[e+6],w=Ta(),p=Oe;Oe+=12*d,Oe=Oe+3>>2<<2;var E=Oe;if(Oe+=4*Se[e+9],Oe=Oe+3>>2<<2,Se[e+4]=p,Se[e+7]=E,s)var A=N(t),g=A;else var y=T(t,1),g=y;var g,m=Ae[Se[e+3]]<<24>>24==0?g:0,S=Se[e+12]+f+10*Se[e+10]|0;if(0==(0|m))var M=0;else var C=S/8+S|0,R=B(17,m,C,a),M=R;var M;Oa(w);var c=M}var c;return Oe=i,c}function Z(r){var a=r+4|0,e=Se[a>>2];va(e),Se[a>>2]=0}function Q(r,a,e){var i,v=r+4|0,t=Me[v>>2],f=0==(0|t);do if(!f){var i=(r+8|0)>>2,_=Me[i];if((_+e|0)>>>0>Me[r+12>>2]>>>0){tr(r,e);var s=Me[v>>2];if(0==(0|s))break;var n=s,o=Se[i]}else var n=t,o=_;var o,n;Pa(n+o|0,a,e,1);var l=Se[i]+e|0;Se[i]=l}while(0)}function q(r,a,e){var i,v,t=a+e|0,f=(0|e)>0;r:do if(f)for(var _=t,s=r+4|0,i=(r+8|0)>>2,n=r+12|0,o=a;;){var o,l=(_-o|0)>3;a:do{if(l){if(Ae[o]<<24>>24!=95){v=21;break}if(Ae[o+1|0]<<24>>24!=95){v=21;break}if(Ae[o+2|0]<<24>>24!=85){v=21;break}for(var b=o+3|0,k=0;;){var k,b;if(b>>>0>=t>>>0){v=21;break a}var u=ge[b],c=u<<24>>24;if((u-48&255&255)<10)var h=c-48|0;else if((u-65&255&255)<6)var h=c-55|0;else{if((u-97&255&255)>=6)break;var h=c-87|0}var h,b=b+1|0,k=(k<<4)+h|0}if(!(u<<24>>24==95&k>>>0<256)){v=21;break}var d=Me[s>>2],w=0==(0|d);do if(!w){var p=Me[i];if(p>>>0>=Me[n>>2]>>>0)break;Se[i]=p+1|0,Ae[d+p|0]=255&k;var E=b;v=25;break a}while(0);Y(r,k);var E=b;v=25;break}v=21}while(0);a:do if(21==v){var A=Me[s>>2],g=0==(0|A);do if(!g){var y=Me[i];if(y>>>0>=Me[n>>2]>>>0)break;var m=Ae[o];Se[i]=y+1|0,Ae[A+y|0]=m;var E=o;break a}while(0);var S=Ae[o]<<24>>24;Y(r,S);var E=o}while(0);var E,M=E+1|0;if(M>>>0>=t>>>0)break r;var o=M}while(0)}function $(r,a){var e,i,v,t,f,_,s,n=r>>2,o=Se[a>>2];r:do if(22==(0|o)||25==(0|o)){var l=Me[n+1],b=0==(0|l);do if(!b){var _=(r+8|0)>>2,k=Me[_];if((k+9|0)>>>0>Me[n+3]>>>0)break;for(var u=l+k|0,c=0|He.__str147,h=u,d=c+9;c>2,A=Me[f];if((A+9|0)>>>0>Me[n+3]>>>0)break;for(var g=p+A|0,c=0|He.__str148,h=g,d=c+9;c>2,M=Me[t];if((M+6|0)>>>0>Me[n+3]>>>0)break;var C=m+M|0;Ae[C]=Ae[0|He.__str149],Ae[C+1]=Ae[(0|He.__str149)+1],Ae[C+2]=Ae[(0|He.__str149)+2],Ae[C+3]=Ae[(0|He.__str149)+3],Ae[C+4]=Ae[(0|He.__str149)+4],Ae[C+5]=Ae[(0|He.__str149)+5];var R=Se[t]+6|0;Se[t]=R;break r}while(0);Q(r,0|He.__str149,6)}else if(28==(0|o)){var T=Me[n+1],O=0==(0|T);do{if(!O){var N=r+8|0,I=Me[N>>2];if(I>>>0>=Me[n+3]>>>0){s=17;break}Se[N>>2]=I+1|0,Ae[T+I|0]=32,s=18;break}s=17}while(0);17==s&&Y(r,32);var P=Se[a+8>>2];H(r,P)}else if(29==(0|o)){if(0!=(4&Se[n]|0))break;var D=Me[n+1],L=0==(0|D);do if(!L){var F=r+8|0,X=Me[F>>2];if(X>>>0>=Me[n+3]>>>0)break;Se[F>>2]=X+1|0,Ae[D+X|0]=42;break r}while(0);Y(r,42)}else if(30==(0|o)){var j=Me[n+1],U=0==(0|j);do if(!U){var x=r+8|0,z=Me[x>>2];if(z>>>0>=Me[n+3]>>>0)break;Se[x>>2]=z+1|0,Ae[j+z|0]=38;break r}while(0);Y(r,38)}else if(31==(0|o)){var V=Me[n+1],B=0==(0|V);do if(!B){var v=(r+8|0)>>2,K=Me[v];if((K+8|0)>>>0>Me[n+3]>>>0)break;var G=V+K|0,W=0|G;oe=1886220131,Ae[W]=255&oe,oe>>=8,Ae[W+1]=255&oe,oe>>=8,Ae[W+2]=255&oe,oe>>=8,Ae[W+3]=255&oe;var Z=G+4|0;oe=544761196,Ae[Z]=255&oe,oe>>=8,Ae[Z+1]=255&oe,oe>>=8,Ae[Z+2]=255&oe,oe>>=8,Ae[Z+3]=255&oe;var q=Se[v]+8|0;Se[v]=q;break r}while(0);Q(r,0|He.__str150,8)}else if(32==(0|o)){var $=Me[n+1],J=0==(0|$);do if(!J){var i=(r+8|0)>>2,rr=Me[i];if((rr+10|0)>>>0>Me[n+3]>>>0)break;for(var ar=$+rr|0,c=0|He.__str151,h=ar,d=c+10;c>2],tr=0==(0|vr);do{if(!tr){var fr=r+8|0,_r=Me[fr>>2];if(0!=(0|_r)&&Ae[vr+(_r-1)|0]<<24>>24==40){s=42;break}if(_r>>>0>=Me[n+3]>>>0){s=41;break}Se[fr>>2]=_r+1|0,Ae[vr+_r|0]=32,s=42;break}s=41}while(0);41==s&&Y(r,32);var sr=Se[a+4>>2];H(r,sr);var nr=Me[ir>>2],or=0==(0|nr);do if(!or){var e=(r+8|0)>>2,lr=Me[e];if((lr+3|0)>>>0>Me[n+3]>>>0)break;var br=nr+lr|0;Ae[br]=Ae[0|He.__str135],Ae[br+1]=Ae[(0|He.__str135)+1],Ae[br+2]=Ae[(0|He.__str135)+2];var kr=Se[e]+3|0;Se[e]=kr;break r}while(0);Q(r,0|He.__str135,3)}else if(3==(0|o)){var ur=Se[a+4>>2];H(r,ur)}else H(r,a);while(0)}function J(r){var a=r+20|0,e=Se[a>>2];if((0|e)<(0|Se[r+24>>2])){var i=Se[r+16>>2]+12*e|0,v=e+1|0;Se[a>>2]=v;var t=i}else var t=0;var t;return t}function rr(r,a,e){var i,v,t,f,_=r>>2,s=e,t=s>>2,n=0;r:for(;;){var n,s,o=0==(0|s);do if(!o){if(0!=(0|Se[t+2]))break;var l=Se[Se[t+1]>>2];if(29==(0|l)||30==(0|l)){f=9;break r}if(22==(0|l)||23==(0|l)||24==(0|l)||28==(0|l)||31==(0|l)||32==(0|l)||37==(0|l)){var b=Se[_+1];f=12;break r}var s=Se[t],t=s>>2,n=1;continue r}while(0);if(0!=(0|Se[a+4>>2])&0==(0|n)){f=9;break}var k=0,u=r+4|0,v=u>>2;f=22;break}do if(9==f){var c=Se[_+1];if(0==(0|c)){f=17;break}var h=Se[_+2];if(0==(0|h)){var d=c;f=13;break}var w=Ae[c+(h-1)|0];if(w<<24>>24==40||w<<24>>24==42){f=18;break}var b=c;f=12;break}while(0);do if(12==f){var b;if(0==(0|b)){f=17;break}var d=b;f=13;break}while(0);do if(13==f){var d,p=r+8|0,E=Me[p>>2];if(0!=(0|E)&&Ae[d+(E-1)|0]<<24>>24==32){f=18;break}if(E>>>0>=Me[_+3]>>>0){f=17;break}Se[p>>2]=E+1|0,Ae[d+E|0]=32,f=18;break}while(0);do if(17==f){Y(r,32),f=18;break}while(0);r:do if(18==f){var A=r+4|0,g=Me[A>>2],y=0==(0|g);do if(!y){var m=r+8|0,S=Me[m>>2];if(S>>>0>=Me[_+3]>>>0)break;Se[m>>2]=S+1|0,Ae[g+S|0]=40;var k=1,u=A,v=u>>2;break r}while(0);Y(r,40);var k=1,u=A,v=u>>2}while(0);var u,k,i=(r+20|0)>>2,M=Se[i];Se[i]=0,vr(r,e,0);r:do if(k){var C=Me[v],R=0==(0|C);do if(!R){var T=r+8|0,O=Me[T>>2];if(O>>>0>=Me[_+3]>>>0)break;Se[T>>2]=O+1|0,Ae[C+O|0]=41;break r}while(0);Y(r,41)}while(0);var N=Me[v],I=0==(0|N);do{if(!I){var P=r+8|0,D=Me[P>>2];if(D>>>0>=Me[_+3]>>>0){f=30;break}Se[P>>2]=D+1|0,Ae[N+D|0]=40,f=31;break}f=30}while(0);30==f&&Y(r,40);var L=Se[a+8>>2];0!=(0|L)&&H(r,L);var F=Me[v],X=0==(0|F);do{if(!X){var j=r+8|0,U=Me[j>>2];if(U>>>0>=Me[_+3]>>>0){f=36;break}Se[j>>2]=U+1|0,Ae[F+U|0]=41,f=37;break}f=36}while(0);36==f&&Y(r,41),vr(r,e,1),Se[i]=M}function ar(r,a,e){var i,v,t,f=r>>2,_=0==(0|e);do{if(!_){var s=e,v=s>>2;r:for(;;){var s;if(0==(0|s)){var n=1;t=14;break}if(0==(0|Se[v+2])){var o=36==(0|Se[Se[v+1]>>2]),l=1&o^1;if(o){var n=l;t=14;break}var b=r+4|0,k=Me[b>>2],u=0==(0|k);do{if(!u){var i=(r+8|0)>>2,c=Me[i];if((c+2|0)>>>0>Me[f+3]>>>0){t=9;break}var h=k+c|0;oe=10272,Ae[h]=255&oe,oe>>=8,Ae[h+1]=255&oe;var d=Se[i]+2|0;Se[i]=d,vr(r,e,0),t=10;break}t=9}while(0);9==t&&(Q(r,0|He.__str140,2),vr(r,e,0));var w=Me[b>>2],p=0==(0|w);do if(!p){var E=r+8|0,A=Me[E>>2];if(A>>>0>=Me[f+3]>>>0)break;Se[E>>2]=A+1|0,Ae[w+A|0]=41;var g=l;t=15;break r}while(0);Y(r,41);var g=l;t=15;break}var s=Se[v],v=s>>2}if(14==t){var n;vr(r,e,0);var g=n}var g;if(0!=(0|g)){t=17;break}var y=r+4|0;t=21;break}t=17}while(0);r:do if(17==t){var m=r+4|0,S=Me[m>>2],M=0==(0|S);do if(!M){var C=r+8|0,R=Me[C>>2];if(R>>>0>=Me[f+3]>>>0)break;Se[C>>2]=R+1|0,Ae[S+R|0]=32;var y=m;break r}while(0);Y(r,32);var y=m}while(0);var y,T=Me[y>>2],O=0==(0|T);do{if(!O){var N=r+8|0,I=Me[N>>2];if(I>>>0>=Me[f+3]>>>0){t=24;break}Se[N>>2]=I+1|0,Ae[T+I|0]=91,t=25;break}t=24}while(0);24==t&&Y(r,91);var P=Se[a+4>>2];0!=(0|P)&&H(r,P);var D=Me[y>>2],L=0==(0|D);do{if(!L){var F=r+8|0,X=Me[F>>2];if(X>>>0>=Me[f+3]>>>0){t=30;break}Se[F>>2]=X+1|0,Ae[D+X|0]=93,t=31;break}t=30}while(0);30==t&&Y(r,93)}function er(r,a){var e,i,v,t,f,_,s=Oe;Oe+=8;var n,o=s,_=(a+4|0)>>2,l=Se[_];if(4==(0|Se[l>>2])){var f=(r+20|0)>>2,b=Se[f];Se[f]=0;var t=(r+16|0)>>2,k=Se[t],u=0|o;Se[u>>2]=k,Se[t]=o;var c=Se[_];Se[o+4>>2]=c;var h=Se[c+4>>2];H(r,h);var d=Se[u>>2];Se[t]=d;var v=(r+4|0)>>2,w=Me[v],p=0==(0|w);do{if(!p){var i=(r+8|0)>>2,E=Me[i],A=0==(0|E);do if(!A){if(Ae[w+(E-1)|0]<<24>>24!=60)break;E>>>0>2]>>>0?(Se[i]=E+1|0,Ae[w+E|0]=32):Y(r,32)}while(0);var g=Me[v];if(0==(0|g)){n=12;break}var y=Me[i];if(y>>>0>=Me[r+12>>2]>>>0){n=12;break}Se[i]=y+1|0,Ae[g+y|0]=60,n=13;break}n=12}while(0);12==n&&Y(r,60);var m=Se[Se[_]+8>>2];H(r,m);var S=Me[v],M=0==(0|S);do{if(!M){var e=(r+8|0)>>2,C=Me[e],R=0==(0|C);do if(!R){if(Ae[S+(C-1)|0]<<24>>24!=62)break;C>>>0>2]>>>0?(Se[e]=C+1|0,Ae[S+C|0]=32):Y(r,32)}while(0);var T=Me[v];if(0==(0|T)){n=22;break}var O=Me[e];if(O>>>0>=Me[r+12>>2]>>>0){n=22;break}Se[e]=O+1|0,Ae[T+O|0]=62,n=23;break}n=22}while(0);22==n&&Y(r,62),Se[f]=b}else H(r,l);Oe=s}function ir(r,a){var e,i=40==(0|Se[a>>2]);r:do if(i){var v=Me[r+4>>2],t=0==(0|v);do{if(!t){var e=(r+8|0)>>2,f=Me[e],_=a+4|0,s=Me[_>>2],n=Me[s+8>>2];if((n+f|0)>>>0>Me[r+12>>2]>>>0){var o=s,l=n;break}var b=v+f|0,k=Se[s+4>>2];Pa(b,k,n,1);var u=Se[e]+Se[Se[_>>2]+8>>2]|0;Se[e]=u;break r}var c=Me[a+4>>2],o=c,l=Se[c+8>>2]}while(0);var l,o,h=Se[o+4>>2];Q(r,h,l)}else H(r,a);while(0)}function vr(r,a,e){var i,v,t,f,_,f=(r+4|0)>>2,s=0==(0|e),t=(r+16|0)>>2;r:do if(s)for(var n=a;;){var n;if(0==(0|n)){_=29;break r}if(0==(0|Se[f])){_=29;break r}var o=n+8|0,l=0==(0|Se[o>>2]);do if(l){var b=n+4|0;if((Se[Se[b>>2]>>2]-25|0)>>>0<3)break;Se[o>>2]=1;var k=Me[t],u=Se[n+12>>2];Se[t]=u;var c=Me[b>>2],h=Se[c>>2];if(35==(0|h)){var d=n,w=k,p=c;_=14;break r}if(36==(0|h)){var E=n,A=k,g=c;_=15;break r}if(2==(0|h)){var y=k,m=b;_=16;break r}$(r,c),Se[t]=k}while(0);var n=Se[n>>2]}else for(var S=a;;){var S;if(0==(0|S)){_=29;break r}if(0==(0|Se[f])){_=29;break r}var M=S+8|0;if(0==(0|Se[M>>2])){Se[M>>2]=1;var C=Me[t],R=Se[S+12>>2];Se[t]=R;var T=S+4|0,O=Me[T>>2],N=Se[O>>2];if(35==(0|N)){var d=S,w=C,p=O;_=14;break r}if(36==(0|N)){var E=S,A=C,g=O;_=15;break r}if(2==(0|N)){var y=C,m=T;_=16;break r}$(r,O),Se[t]=C}var S=Se[S>>2]}while(0);if(14==_){var p,w,d,I=Se[d>>2];rr(r,p,I),Se[t]=w}else if(15==_){var g,A,E,P=Se[E>>2];ar(r,g,P),Se[t]=A}else if(16==_){var m,y,v=(r+20|0)>>2,D=Se[v];Se[v]=0;var L=Se[Se[m>>2]+4>>2];H(r,L),Se[v]=D;var F=0==(4&Se[r>>2]|0),X=Me[f],j=0!=(0|X);r:do if(F){do if(j){var i=(r+8|0)>>2,U=Me[i];if((U+2|0)>>>0>Me[r+12>>2]>>>0)break;var x=X+U|0;oe=14906,Ae[x]=255&oe,oe>>=8,Ae[x+1]=255&oe;var z=Se[i]+2|0;Se[i]=z;break r}while(0);Q(r,0|He.__str120,2)}else{do if(j){var V=r+8|0,B=Me[V>>2];if(B>>>0>=Me[r+12>>2]>>>0)break;Se[V>>2]=B+1|0,Ae[X+B|0]=46;break r}while(0);Y(r,46)}while(0);var K=Me[Se[m>>2]+8>>2],G=(Se[K>>2]-25|0)>>>0<3;r:do if(G)for(var W=K;;){var W,Z=Me[W+4>>2];if((Se[Z>>2]-25|0)>>>0>=3){var q=Z;break r}var W=Z}else var q=K;while(0);var q;H(r,q),Se[t]=y}}function tr(r,a){var e,e=(r+4|0)>>2,i=Se[e],v=0==(0|i);r:do if(!v){for(var t=Se[r+8>>2]+a|0,f=r+12|0,_=Se[f>>2],s=i;;){var s,_;if(t>>>0<=_>>>0)break r;var n=_<<1,o=fa(s,n);if(0==(0|o))break;Se[e]=o,Se[f>>2]=n;var _=n,s=o}var l=Se[e];va(l),Se[e]=0,Se[r+24>>2]=1}while(0)}function fr(r,a,e){var i,v=J(r),i=v>>2;return 0!=(0|v)&&(Se[i]=21,Se[i+1]=a,Se[i+2]=e),v}function _r(r){var a,a=(r+12|0)>>2,e=Se[a],i=Ae[e]<<24>>24;if(88==(0|i)){var v=e+1|0;Se[a]=v;var t=nr(r),f=Se[a],_=f+1|0;Se[a]=_;var s=Ae[f]<<24>>24==69?t:0,n=s}else if(76==(0|i))var o=or(r),n=o;else var l=N(r),n=l;var n;return n}function sr(r){var a,a=(r+12|0)>>2,e=Se[a],i=Ae[e];if(i<<24>>24==110){var v=e+1|0;Se[a]=v;var t=1,f=Ae[v],_=v}else var t=0,f=i,_=e;var _,f,t,s=(f-48&255&255)<10;r:do if(s)for(var n=f,o=0,l=_;;){var l,o,n,b=(n<<24>>24)-48+10*o|0,k=l+1|0;Se[a]=k;var u=ge[k];if((u-48&255&255)>=10){var c=b;break r}var n=u,o=b,l=k}else var c=0;while(0);var c,h=0==(0|t)?c:0|-c;return h}function nr(r){var a,e,a=(r+12|0)>>2,i=Se[a],v=Ae[i];do{if(v<<24>>24==76){var t=or(r),f=t;e=21;break}if(v<<24>>24==84){var _=x(r),f=_;e=21;break}if(v<<24>>24==115){if(Ae[i+1|0]<<24>>24!=114){e=8;break}var s=i+2|0;Se[a]=s;var n=N(r),o=br(r);if(Ae[Se[a]]<<24>>24==73){var l=z(r),b=D(r,4,o,l),k=D(r,1,n,b),f=k;e=21;break}var u=D(r,1,n,o),f=u;e=21;break}e=8}while(0);r:do if(8==e){var c=kr(r);if(0==(0|c)){var f=0;break}var h=0|c,d=Se[h>>2],w=40==(0|d);do{if(w){var p=c+4|0,E=r+48|0,A=Se[Se[p>>2]+8>>2]-2+Se[E>>2]|0;Se[E>>2]=A;var g=Se[h>>2];if(40!=(0|g)){var y=g;e=13;break}var m=Se[p>>2],S=Se[m>>2],M=Da(S,0|He.__str90);if(0!=(0|M)){var C=m;e=15;break}var R=N(r),T=D(r,43,c,R),f=T;break r}var y=d;e=13}while(0);do if(13==e){var y;if(40==(0|y)){var C=Se[c+4>>2];e=15;break}if(41==(0|y)){var O=c+4|0;e=17;break}if(42==(0|y)){e=18;break}var f=0;break r}while(0);do if(15==e){var C,O=C+12|0;e=17;break}while(0);do if(17==e){var O,I=Se[O>>2];if(1==(0|I))break;if(2==(0|I)){var P=nr(r),L=nr(r),F=D(r,45,P,L),X=D(r,44,c,F);return X}if(3==(0|I)){var j=nr(r),U=nr(r),V=nr(r),B=D(r,48,U,V),H=D(r,47,j,B),K=D(r,46,c,H);return K}var f=0;break r}while(0);var Y=nr(r),G=D(r,43,c,Y);return G}while(0);var f;return f}function or(r){var a,a=(r+12|0)>>2,e=Se[a],i=e+1|0;Se[a]=i;var v=Ae[e]<<24>>24==76;r:do if(v){if(Ae[i]<<24>>24==95)var t=T(r,0),f=t;else{var _=N(r);if(0==(0|_)){var s=0;break}var n=33==(0|Se[_>>2]);do if(n){var o=Se[_+4>>2];if(0==(0|Se[o+16>>2]))break;var l=r+48|0,b=Se[l>>2]-Se[o+4>>2]|0;Se[l>>2]=b}while(0);var k=Se[a];if(Ae[k]<<24>>24==110){var u=k+1|0;Se[a]=u;var c=50,h=u}else var c=49,h=k;for(var h,c,d=h;;){var d,w=Ae[d];if(w<<24>>24==69)break;if(w<<24>>24==0){var s=0;break r}var p=d+1|0;Se[a]=p;var d=p}var E=lr(r,h,d-h|0),A=D(r,c,_,E),f=A}var f,g=Se[a],y=g+1|0;Se[a]=y;var m=Ae[g]<<24>>24==69?f:0,s=m}else var s=0;while(0);var s;return s}function lr(r,a,e){var i=J(r),v=m(i,a,e),t=0==(0|v)?0:i;return t}function br(r){var a=r+12|0,e=Me[a>>2],i=ge[e],v=(i-48&255&255)<10;do if(v)var t=L(r),f=t;else if((i-97&255&255)<26){var _=kr(r);if(0==(0|_)){var f=0;break}if(40!=(0|Se[_>>2])){var f=_;break}var s=r+48|0,n=Se[Se[_+4>>2]+8>>2]+Se[s>>2]+7|0;Se[s>>2]=n;var f=_}else if(i<<24>>24==67||i<<24>>24==68)var o=hr(r),f=o;else{if(i<<24>>24!=76){var f=0;break}Se[a>>2]=e+1|0;var l=L(r);if(0==(0|l)){var f=0;break}var b=dr(r),k=0==(0|b)?0:l,f=k}while(0);var f;return f}function kr(r){var a,e,a=(r+12|0)>>2,i=Se[a],v=i+1|0;Se[a]=v;var t=ge[i],f=i+2|0;Se[a]=f;var _=ge[v];do{if(t<<24>>24==118){if((_-48&255&255)>=10){var s=49,n=0;e=6;break}var o=(_<<24>>24)-48|0,l=L(r),b=ur(r,o,l),k=b;e=14;break}if(t<<24>>24==99){if(_<<24>>24!=118){var s=49,n=0;e=6;break}var u=N(r),c=D(r,42,u,0),k=c;e=14;break}var s=49,n=0;e=6}while(0);r:do if(6==e){for(;;){var n,s,h=(s-n)/2+n|0,d=(h<<4)+ri|0,w=Se[d>>2],p=Ae[w],E=t<<24>>24==p<<24>>24;if(E&&_<<24>>24==Ae[w+1|0]<<24>>24)break;var A=t<<24>>24>24;do if(A)var g=h,y=n;else{if(E&&_<<24>>24>24){var g=h,y=n;break}var g=s,y=h+1|0}while(0);var y,g;if((0|y)==(0|g)){var k=0;break r}var s=g,n=y}var m=cr(r,d),k=m}while(0);var k;return k}function ur(r,a,e){var i=J(r),v=S(i,a,e),t=0==(0|v)?0:i;return t}function cr(r,a){var e=J(r);return 0!=(0|e)&&(Se[e>>2]=40,Se[e+4>>2]=a),e}function hr(r){var a,e,i=Se[r+44>>2],e=i>>2,v=0==(0|i);do if(!v){var t=Se[e];if(0==(0|t)){var f=r+48|0,_=Se[f>>2]+Se[e+2]|0;Se[f>>2]=_}else{if(21!=(0|t))break;var s=r+48|0,n=Se[s>>2]+Se[e+2]|0;Se[s>>2]=n}}while(0);var a=(r+12|0)>>2,o=Se[a],l=o+1|0;Se[a]=l;var b=Ae[o]<<24>>24;do if(67==(0|b)){var k=o+2|0;Se[a]=k;var u=Ae[l]<<24>>24;if(49==(0|u))var c=1;else if(50==(0|u))var c=2;else{if(51!=(0|u)){var h=0;break}var c=3}var c,d=wr(r,c,i),h=d}else if(68==(0|b)){var w=o+2|0;Se[a]=w;var p=Ae[l]<<24>>24;if(48==(0|p))var E=1;else if(49==(0|p))var E=2;else{if(50!=(0|p)){var h=0;break}var E=3}var E,A=pr(r,E,i),h=A}else var h=0;while(0);var h;return h}function dr(r){var a=r+12|0,e=Se[a>>2];if(Ae[e]<<24>>24==95){var i=e+1|0;Se[a>>2]=i;var v=sr(r),t=v>>>31^1}else var t=1;var t;return t}function wr(r,a,e){var i=J(r),v=M(i,a,e),t=0==(0|v)?0:i;return t}function pr(r,a,e){var i=J(r),v=C(i,a,e),t=0==(0|v)?0:i;return t}function Er(r,a){var e=J(r);return 0!=(0|e)&&(Se[e>>2]=5,Se[e+4>>2]=a),e}function Ar(r){var a,a=(r+12|0)>>2,e=Se[a],i=Ae[e]<<24>>24;do if(78==(0|i))var v=gr(r),t=v;else if(90==(0|i))var f=yr(r),t=f;else if(76==(0|i))var _=br(r),t=_;else if(83==(0|i)){if(Ae[e+1|0]<<24>>24==116){var s=e+2|0;Se[a]=s;var n=lr(r,0|He.__str152,3),o=br(r),l=D(r,1,n,o),b=r+48|0,k=Se[b>>2]+3|0;Se[b>>2]=k;var u=0,c=l}else var h=V(r,0),u=1,c=h;var c,u;if(Ae[Se[a]]<<24>>24!=73){var t=c;break}if(0==(0|u)){var d=R(r,c);if(0==(0|d)){var t=0;break}}var w=z(r),p=D(r,4,c,w),t=p}else{var E=br(r);if(Ae[Se[a]]<<24>>24!=73){var t=E;break}var A=R(r,E);if(0==(0|A)){var t=0;break}var g=z(r),y=D(r,4,E,g),t=y}while(0);var t;return t}function gr(r){var a,e=Oe;Oe+=4;var i=e,a=(r+12|0)>>2,v=Se[a],t=v+1|0;Se[a]=t;var f=Ae[v]<<24>>24==78;do if(f){var _=I(r,i,1);if(0==(0|_)){var s=0;break}var n=mr(r);if(Se[_>>2]=n,0==(0|n)){var s=0;break}var o=Se[a],l=o+1|0;if(Se[a]=l,Ae[o]<<24>>24!=69){var s=0;break}var s=Se[i>>2]}else var s=0;while(0);var s;return Oe=e,s}function yr(r){var a,a=(r+12|0)>>2,e=Se[a],i=e+1|0;Se[a]=i;var v=Ae[e]<<24>>24==90;do if(v){var t=O(r,0),f=Se[a],_=f+1|0;if(Se[a]=_,Ae[f]<<24>>24!=69){var s=0;break}if(Ae[_]<<24>>24==115){var n=f+2|0;Se[a]=n;var o=dr(r);if(0==(0|o)){var s=0;break}var l=lr(r,0|He.__str168,14),b=D(r,2,t,l),s=b}else{var k=Ar(r),u=dr(r);if(0==(0|u)){var s=0;break}var c=D(r,2,t,k),s=c}}else var s=0;while(0);var s;return s}function mr(r){var a,e=r+12|0,i=0;r:for(;;){var i,v=ge[Se[e>>2]];if(v<<24>>24==0){var t=0;break}var f=(v-48&255&255)<10|(v-97&255&255)<26;do{if(!f){if(v<<24>>24==76||v<<24>>24==68||v<<24>>24==67){a=5;break}if(v<<24>>24==83){var _=V(r,1),s=_;a=10;break}if(v<<24>>24==73){if(0==(0|i)){var t=0;break r}var n=z(r),o=4,l=n;a=11;break}if(v<<24>>24==84){var b=x(r),s=b;a=10;break}if(v<<24>>24==69){var t=i;break r}var t=0;break r}a=5}while(0);do if(5==a){var k=br(r),s=k;a=10;break}while(0);do if(10==a){var s;if(0==(0|i)){var u=s;a=12;break}var o=1,l=s;a=11;break}while(0);if(11==a)var l,o,c=D(r,o,i,l),u=c;var u;if(v<<24>>24!=83)if(Ae[Se[e>>2]]<<24>>24!=69){var h=R(r,u);if(0==(0|h)){var t=0;break}var i=u}else var i=u;else var i=u}var t;return t}function Sr(r,a){var e,i,v=Oe;Oe+=4;var t=v,i=t>>2,e=(r+12|0)>>2,f=Se[e];if(Ae[f]<<24>>24==74){var _=f+1|0;Se[e]=_;var s=1}else var s=a;var s;Se[i]=0;var n=s,o=0,l=t;r:for(;;)for(var l,o,n,b=n,k=o;;){var k,b,u=Ae[Se[e]];if(u<<24>>24==0||u<<24>>24==69){var c=Se[i];if(0==(0|c)){var h=0;break r}var d=0==(0|Se[c+8>>2]);do if(d){var w=Se[c+4>>2];if(33!=(0|Se[w>>2])){var p=c;break}var E=Se[w+4>>2];if(9!=(0|Se[E+16>>2])){var p=c;break}var A=r+48|0,g=Se[A>>2]-Se[E+4>>2]|0;Se[A>>2]=g,Se[i]=0;var p=0}else var p=c;while(0);var p,y=D(r,35,k,p),h=y;break r}var m=N(r);if(0==(0|m)){var h=0;break r}if(0==(0|b)){var S=D(r,38,m,0);if(Se[l>>2]=S,0==(0|S)){var h=0;break r}var n=0,o=k,l=S+8|0;continue r}var b=0,k=m}var h;return Oe=v,h}function Mr(r){for(var a=r;;){var a;if(0==(0|a)){var e=0;break}var i=Se[a>>2];if(1!=(0|i)&&2!=(0|i)){if(6==(0|i)||7==(0|i)||42==(0|i)){var e=1;break}var e=0;break}var a=Se[a+8>>2]}var e;return e}function Cr(r){var a=r>>2;Se[a+3]=0,Se[a+2]=0,Se[a+1]=0,Se[a]=0,Se[a+4]=0}function Rr(r,a){var e,e=(r+12|0)>>2,i=Se[e],v=(Se[r+4>>2]-i|0)<(0|a);r:do if(v)var t=0;else{var f=i+a|0;Se[e]=f;var _=0==(4&Se[r+8>>2]|0);do if(!_){if(Ae[f]<<24>>24!=36)break;var s=a+(i+1)|0;Se[e]=s}while(0);var n=(0|a)>9;do if(n){var o=La(i,0|He.__str117,8);if(0!=(0|o))break;var l=Ae[i+8|0];if(l<<24>>24!=46&&l<<24>>24!=95&&l<<24>>24!=36)break;if(Ae[i+9|0]<<24>>24!=78)break;var b=r+48|0,k=22-a+Se[b>>2]|0;Se[b>>2]=k;var u=lr(r,0|He.__str169,21),t=u;break r}while(0);var c=lr(r,i,a),t=c}while(0);var t;return t}function Tr(r){var a,e,e=(r+48|0)>>2,i=Se[e],v=i+20|0;Se[e]=v;var a=(r+12|0)>>2,t=Se[a],f=t+1|0;Se[a]=f;var _=Ae[t];do if(_<<24>>24==84){var s=t+2|0;Se[a]=s;var n=Ae[f]<<24>>24;if(86==(0|n)){var o=i+15|0;Se[e]=o;var l=N(r),b=D(r,8,l,0),k=b}else if(84==(0|n)){var u=i+10|0;Se[e]=u;var c=N(r),h=D(r,9,c,0),k=h}else if(73==(0|n))var d=N(r),w=D(r,11,d,0),k=w;else if(83==(0|n))var p=N(r),E=D(r,12,p,0),k=E;else if(104==(0|n)){var A=Nr(r,104);if(0==(0|A)){var k=0;break}var g=O(r,0),y=D(r,14,g,0),k=y}else if(118==(0|n)){var m=Nr(r,118);if(0==(0|m)){var k=0;break}var S=O(r,0),M=D(r,15,S,0),k=M}else if(99==(0|n)){var C=Nr(r,0);if(0==(0|C)){var k=0;break}var R=Nr(r,0);if(0==(0|R)){var k=0;break}var T=O(r,0),I=D(r,16,T,0),k=I}else if(67==(0|n)){var P=N(r),L=sr(r);if((0|L)<0){var k=0;break}var F=Se[a],X=F+1|0;if(Se[a]=X,Ae[F]<<24>>24!=95){var k=0;break}var j=N(r),U=Se[e]+5|0;Se[e]=U;var x=D(r,10,j,P),k=x}else if(70==(0|n))var z=N(r),V=D(r,13,z,0),k=V;else{if(74!=(0|n)){var k=0;break}var B=N(r),H=D(r,17,B,0),k=H}}else if(_<<24>>24==71){var K=t+2|0;Se[a]=K;var Y=Ae[f]<<24>>24;if(86==(0|Y))var G=Ar(r),W=D(r,18,G,0),k=W;else if(82==(0|Y))var Z=Ar(r),Q=D(r,19,Z,0),k=Q;else{if(65!=(0|Y)){var k=0;break}var q=O(r,0),$=D(r,20,q,0),k=$}}else var k=0;while(0);var k;return k}function Or(r){for(var a,e=r,a=e>>2;;){var e;if(0==(0|e)){var i=0;break}var v=Se[a];if(4==(0|v)){var t=Se[a+1],f=Mr(t),i=0==(0|f)&1;break}if(25!=(0|v)&&26!=(0|v)&&27!=(0|v)){var i=0;break}var e=Se[a+1],a=e>>2}var i;return i}function Nr(r,a){var e;if(0==(0|a)){var i=r+12|0,v=Se[i>>2],t=v+1|0;Se[i>>2]=t;var f=Ae[v]<<24>>24}else var f=a;var f;do{if(104==(0|f)){var _=(sr(r),r+12|0);e=7;break}if(118==(0|f)){var s=(sr(r),r+12|0),n=Se[s>>2],o=n+1|0;if(Se[s>>2]=o,Ae[n]<<24>>24!=95){var l=0;e=8;break}var _=(sr(r),s);e=7;break}var l=0;e=8}while(0);if(7==e){var _,b=Se[_>>2],k=b+1|0;Se[_>>2]=k;var l=Ae[b]<<24>>24==95&1}var l;return l}function Ir(r){var a,e,i=r>>2,v=Oe;Oe+=56;var t,f=v,_=v+8,s=v+16,n=v+36,e=(0|r)>>2,o=Se[e],l=0==(8192&o|0);r:do{if(l){var a=(r+12|0)>>2,b=Se[a];if(Ae[b]<<24>>24!=63){var k=0;t=111;break}var u=b+1|0;Se[a]=u;var c=Ae[u];do if(c<<24>>24==63){if(Ae[b+2|0]<<24>>24==36){var h=b+3|0;if(Ae[h]<<24>>24!=63){var d=5;t=90;break}Se[a]=h;var w=6,p=h}else var w=0,p=u;var p,w,E=p+1|0;Se[a]=E;var A=Ae[E]<<24>>24;do if(48==(0|A)){var g=1;t=81}else{if(49==(0|A)){var g=2;t=81;break}if(50!=(0|A)){if(51==(0|A)){var y=0|He.__str2172,m=E;t=82;break}if(52==(0|A)){var y=0|He.__str3173,m=E;t=82;break}if(53==(0|A)){var y=0|He.__str4174,m=E;t=82;break}if(54==(0|A)){var y=0|He.__str5175,m=E;t=82;break}if(55==(0|A)){var y=0|He.__str6176,m=E;t=82;break}if(56==(0|A)){var y=0|He.__str7177,m=E;t=82;break}if(57==(0|A)){var y=0|He.__str8178,m=E;t=82;break}if(65==(0|A)){var y=0|He.__str9179,m=E;t=82;break}if(66==(0|A)){Se[a]=p+2|0;var S=0|He.__str10180,M=3;t=88;break}if(67==(0|A)){var y=0|He.__str11181,m=E;t=82;break}if(68==(0|A)){var y=0|He.__str12182,m=E;t=82;break}if(69==(0|A)){var y=0|He.__str13183,m=E;t=82;break}if(70==(0|A)){var y=0|He.__str14184,m=E;t=82;break}if(71==(0|A)){var y=0|He.__str15185,m=E;t=82;break}if(72==(0|A)){var y=0|He.__str16186,m=E;t=82;break}if(73==(0|A)){var y=0|He.__str17187,m=E;t=82;break}if(74==(0|A)){var y=0|He.__str18188,m=E;t=82;break}if(75==(0|A)){var y=0|He.__str19189,m=E;t=82;break}if(76==(0|A)){var y=0|He.__str20190,m=E;t=82;break}if(77==(0|A)){var y=0|He.__str21191,m=E;t=82;break}if(78==(0|A)){var y=0|He.__str22192,m=E;t=82;break}if(79==(0|A)){var y=0|He.__str23193,m=E;t=82;break}if(80==(0|A)){var y=0|He.__str24194,m=E;t=82;break}if(81==(0|A)){var y=0|He.__str25195,m=E;t=82;break}if(82==(0|A)){var y=0|He.__str26196,m=E;t=82;break}if(83==(0|A)){var y=0|He.__str27197,m=E;t=82;break}if(84==(0|A)){var y=0|He.__str28198,m=E;t=82;break}if(85==(0|A)){var y=0|He.__str29199,m=E;t=82;break}if(86==(0|A)){var y=0|He.__str30200,m=E;t=82;break}if(87==(0|A)){var y=0|He.__str31201,m=E;t=82;break}if(88==(0|A)){var y=0|He.__str32202,m=E;t=82;break}if(89==(0|A)){var y=0|He.__str33203,m=E;t=82;break}if(90==(0|A)){var y=0|He.__str34204,m=E;t=82;break}if(95==(0|A)){var C=p+2|0;Se[a]=C;var R=Ae[C]<<24>>24;if(48==(0|R)){var y=0|He.__str35205,m=C;t=82;break}if(49==(0|R)){var y=0|He.__str36206,m=C;t=82;break}if(50==(0|R)){var y=0|He.__str37207,m=C;t=82;break}if(51==(0|R)){var y=0|He.__str38208,m=C;t=82;break}if(52==(0|R)){var y=0|He.__str39209,m=C;t=82;break}if(53==(0|R)){var y=0|He.__str40210,m=C;t=82;break}if(54==(0|R)){var y=0|He.__str41211,m=C;t=82;break}if(55==(0|R)){var y=0|He.__str42212,m=C;t=82;break}if(56==(0|R)){var y=0|He.__str43213,m=C;t=82;break}if(57==(0|R)){var y=0|He.__str44214,m=C;t=82;break}if(65==(0|R)){var y=0|He.__str45215,m=C;t=82;break}if(66==(0|R)){var y=0|He.__str46216,m=C;t=82;break}if(67==(0|R)){Se[a]=p+3|0;var T=0|He.__str47217;t=84;break}if(68==(0|R)){var y=0|He.__str48218,m=C;t=82;break}if(69==(0|R)){var y=0|He.__str49219,m=C;t=82;break}if(70==(0|R)){var y=0|He.__str50220,m=C;t=82;break}if(71==(0|R)){var y=0|He.__str51221,m=C;t=82;break}if(72==(0|R)){var y=0|He.__str52222,m=C;t=82;break}if(73==(0|R)){var y=0|He.__str53223,m=C;t=82;break}if(74==(0|R)){var y=0|He.__str54224,m=C;t=82;break}if(75==(0|R)){var y=0|He.__str55225,m=C;t=82;break}if(76==(0|R)){var y=0|He.__str56226,m=C;t=82;break}if(77==(0|R)){var y=0|He.__str57227,m=C;t=82;break}if(78==(0|R)){var y=0|He.__str58228,m=C;t=82;break}if(79==(0|R)){var y=0|He.__str59229,m=C;t=82;break}if(82==(0|R)){var O=4|o;Se[e]=O;var N=p+3|0;Se[a]=N;var I=Ae[N]<<24>>24;if(48==(0|I)){Se[a]=p+4|0,Cr(s);var P=(Pr(r,_,s,0),Se[_>>2]),D=Se[_+4>>2],L=Dr(r,0|He.__str60230,(ne=Oe,Oe+=8,Se[ne>>2]=P,Se[ne+4>>2]=D,ne)),F=Se[a]-1|0;Se[a]=F;var y=L,m=F;t=82;break}if(49==(0|I)){Se[a]=p+4|0;var X=Lr(r),j=Lr(r),U=Lr(r),x=Lr(r),z=Se[a]-1|0;Se[a]=z;var V=Dr(r,0|He.__str61231,(ne=Oe,Oe+=16,Se[ne>>2]=X,Se[ne+4>>2]=j,Se[ne+8>>2]=U,Se[ne+12>>2]=x,ne)),y=V,m=Se[a];t=82;break}if(50==(0|I)){var y=0|He.__str62232,m=N;t=82;break}if(51==(0|I)){var y=0|He.__str63233,m=N;t=82;break}if(52==(0|I)){var y=0|He.__str64234,m=N;t=82;break}var y=0,m=N;t=82;break}if(83==(0|R)){var y=0|He.__str65235,m=C;t=82;break}if(84==(0|R)){var y=0|He.__str66236,m=C;t=82;break}if(85==(0|R)){var y=0|He.__str67237,m=C;t=82;break}if(86==(0|R)){var y=0|He.__str68238,m=C;t=82;break}if(88==(0|R)){var y=0|He.__str69239,m=C;t=82;break}if(89==(0|R)){var y=0|He.__str70240,m=C;t=82;break}var k=0;t=111;break r}var k=0;t=111;break r}var y=0|He.__str1171,m=E;t=82}while(0);do{if(81==t){var g;Se[a]=p+2|0;var B=g;t=83;break}if(82==t){var m,y;if(Se[a]=m+1|0,1==(0|w)||2==(0|w)){var B=w;t=83;break}if(4==(0|w)){var T=y;t=84;break}if(6!=(0|w)){var S=y,M=w;t=88;break}Cr(n);var H=Xr(r,n,0,60,62);if(0==(0|H))var K=y;else var Y=Dr(r,0|He.__str170,(ne=Oe,Oe+=8,Se[ne>>2]=y,Se[ne+4>>2]=H,ne)),K=Y;var K;Se[i+6]=0;var S=K,M=w;t=88;break}}while(0);if(83==t){var B,G=r+40|0,W=Fr(r,0|He._symbol_demangle_dashed_null,-1,G);if(0==(0|W)){var k=0;t=111;break r}var d=B;t=90;break}if(84==t){var T;Se[i+4]=T;var Z=1,Q=T;t=109;break r}if(88==t){var M,S,q=r+40|0,$=Fr(r,S,-1,q);if(0==(0|$)){var k=0;t=111;break r}var d=M;t=90;break}}else{if(c<<24>>24==36){var J=b+2|0;Se[a]=J;var rr=jr(r);Se[i+4]=rr;var ar=0!=(0|rr)&1;t=107;break}var d=0;t=90}while(0);if(90==t){var d,er=Me[a],ir=Ae[er]<<24>>24;if(64==(0|ir))Se[a]=er+1|0;else if(36==(0|ir))t=93;else{var vr=zr(r);if(0==(0|vr)){var k=-1;t=111;break}}if(5==(0|d)){var tr=r+20|0,fr=Se[tr>>2]+1|0;Se[tr>>2]=fr}else if(1==(0|d)||2==(0|d)){if(Me[i+11]>>>0<2){var k=-1;t=111;break}var _r=r+56|0,sr=Me[_r>>2],nr=Se[sr+4>>2];if(1==(0|d))Se[sr>>2]=nr;else{var or=Dr(r,0|He.__str71241,(ne=Oe,Oe+=4,Se[ne>>2]=nr,ne)),lr=Se[_r>>2];Se[lr>>2]=or}var br=4|Se[e];Se[e]=br}else if(3==(0|d)){var kr=Se[e]&-5;Se[e]=kr}var ur=ge[Se[a]];if((ur-48&255&255)<10)var cr=Vr(r),ar=cr;else if((ur-65&255&255)<26)var hr=Br(r,3==(0|d)&1),ar=hr;else{if(ur<<24>>24!=36){var k=-1;t=111;break}var dr=Hr(r),ar=dr}}var ar;if(0==(0|ar)){var k=-1;t=111;break}var Z=ar,Q=Se[i+4];t=109;break}var wr=Pr(r,f,0,0);if(0==(0|wr)){var k=-1;t=111;break}var pr=Se[f>>2],Er=Se[f+4>>2],Ar=Dr(r,0|He.__str170,(ne=Oe,Oe+=8,Se[ne>>2]=pr,Se[ne+4>>2]=Er,ne));Se[i+4]=Ar;var Z=1,Q=Ar;t=109;break}while(0);do if(109==t){var Q,Z;if(0!=(0|Q)){var k=Z;break}Xa(0|He.__str72242,1499,0|He.___func___symbol_demangle,0|He.__str73243);var k=Z}while(0);var k;return Oe=v,k}function Pr(r,a,e,i){var v,t,f,_=Oe;Oe+=24;var s=_,n=_+4,o=_+8,l=_+16,b=_+20;0==(0|a)&&Xa(0|He.__str72242,829,0|He.___func___demangle_datatype,0|He.__str121291);var f=(a+4|0)>>2;Se[f]=0;var t=(0|a)>>2;Se[t]=0;var v=(r+12|0)>>2,k=Me[v],u=k+1|0;Se[v]=u;var c=Ae[k],h=c<<24>>24;do if(95==(0|h)){Se[v]=k+2|0;var d=Ae[u],w=Zr(d);Se[t]=w}else if(67==(0|h)||68==(0|h)||69==(0|h)||70==(0|h)||71==(0|h)||72==(0|h)||73==(0|h)||74==(0|h)||75==(0|h)||77==(0|h)||78==(0|h)||79==(0|h)||88==(0|h)||90==(0|h)){var p=Qr(c);Se[t]=p}else if(84==(0|h)||85==(0|h)||86==(0|h)||89==(0|h)){var E=qr(r);if(0==(0|E))break;var A=0==(32768&Se[r>>2]|0);do if(A)if(84==(0|h))var g=0|He.__str122292;else if(85==(0|h))var g=0|He.__str123293;else if(86==(0|h))var g=0|He.__str124294;else{if(89!=(0|h)){var g=0;break}var g=0|He.__str125295}else var g=0;while(0);var g,y=Dr(r,0|He.__str170,(ne=Oe,Oe+=8,Se[ne>>2]=g,Se[ne+4>>2]=E,ne));Se[t]=y}else if(63==(0|h))if(0==(0|i))$r(a,r,e,63,0);else{var m=Lr(r);if(0==(0|m))break;var S=Dr(r,0|He.__str126296,(ne=Oe,Oe+=4,Se[ne>>2]=m,ne));Se[t]=S}else if(65==(0|h)||66==(0|h))$r(a,r,e,c,i);else if(81==(0|h)||82==(0|h)||83==(0|h)){var M=0==(0|i)?80:c;$r(a,r,e,M,i)}else if(80==(0|h))if(((Ae[u]<<24>>24)-48|0)>>>0<10){var C=k+2|0;if(Se[v]=C,Ae[u]<<24>>24!=54)break;var R=r+44|0,T=Se[R>>2];Se[v]=k+3|0;var O=Ae[C],N=Se[r>>2]&-17,I=Ur(O,s,n,N);if(0==(0|I))break;var P=Pr(r,o,e,0);if(0==(0|P))break;var D=Xr(r,e,1,40,41);if(0==(0|D))break;Se[R>>2]=T;var L=Se[o>>2],F=Se[o+4>>2],X=Se[s>>2],j=Dr(r,0|He.__str127297,(ne=Oe,Oe+=12,Se[ne>>2]=L,Se[ne+4>>2]=F,Se[ne+8>>2]=X,ne));Se[t]=j;var U=Dr(r,0|He.__str128298,(ne=Oe,Oe+=4,Se[ne>>2]=D,ne));Se[f]=U}else $r(a,r,e,80,i);else if(87==(0|h)){if(Ae[u]<<24>>24!=52)break;Se[v]=k+2|0;var x=qr(r);if(0==(0|x))break;if(0==(32768&Se[r>>2]|0)){var z=Dr(r,0|He.__str129299,(ne=Oe,Oe+=4,Se[ne>>2]=x,ne));Se[t]=z}else Se[t]=x}else if(48==(0|h)||49==(0|h)||50==(0|h)||51==(0|h)||52==(0|h)||53==(0|h)||54==(0|h)||55==(0|h)||56==(0|h)||57==(0|h)){var V=h<<1,B=V-96|0,H=Yr(e,B);Se[t]=H;var K=V-95|0,Y=Yr(e,K);Se[f]=Y}else if(36==(0|h)){var G=k+2|0;Se[v]=G;var W=Ae[u]<<24>>24;if(48==(0|W)){var Z=Lr(r);Se[t]=Z}else if(68==(0|W)){var Q=Lr(r);if(0==(0|Q))break;var q=Dr(r,0|He.__str130300,(ne=Oe,Oe+=4,Se[ne>>2]=Q,ne));Se[t]=q}else if(70==(0|W)){var $=Lr(r);if(0==(0|$))break;var J=Lr(r);if(0==(0|J))break;var rr=Dr(r,0|He.__str131301,(ne=Oe,Oe+=8,Se[ne>>2]=$,Se[ne+4>>2]=J,ne));Se[t]=rr}else if(71==(0|W)){var ar=Lr(r);if(0==(0|ar))break;var er=Lr(r);if(0==(0|er))break;var ir=Lr(r);if(0==(0|ir))break;var vr=Dr(r,0|He.__str132302,(ne=Oe,Oe+=12,Se[ne>>2]=ar,Se[ne+4>>2]=er,Se[ne+8>>2]=ir,ne));Se[t]=vr}else if(81==(0|W)){var tr=Lr(r);if(0==(0|tr))break;var fr=Dr(r,0|He.__str133303,(ne=Oe,Oe+=4,Se[ne>>2]=tr,ne));Se[t]=fr}else{if(36!=(0|W))break;if(Ae[G]<<24>>24!=67)break;Se[v]=k+3|0;var _r=xr(r,l,b);if(0==(0|_r))break;var sr=Pr(r,a,e,i);if(0==(0|sr))break;var nr=Se[t],or=Se[l>>2],lr=Dr(r,0|He.__str83253,(ne=Oe,Oe+=8,Se[ne>>2]=nr,Se[ne+4>>2]=or,ne));Se[t]=lr}}while(0);var br=0!=(0|Se[t])&1;return Oe=_,br}function Dr(r,a){var e,i=Oe;Oe+=4;var v=i,e=v>>2,t=v;Se[t>>2]=arguments[Dr.length];var f=1,_=0;r:for(;;){var _,f,s=Ae[a+_|0];do{if(s<<24>>24==0)break r;if(s<<24>>24==37){var n=_+1|0,o=Ae[a+n|0]<<24>>24;if(115==(0|o)){var l=Se[e],b=l,k=l+4|0;Se[e]=k;var u=Se[b>>2];if(0==(0|u)){var c=f,h=n;break}var d=Ca(u),c=d+f|0,h=n;break}if(99==(0|o)){var w=Se[e]+4|0;Se[e]=w;var c=f+1|0,h=n;break}if(37==(0|o))var p=n;else var p=_;var p,c=f+1|0,h=p}else var c=f+1|0,h=_}while(0);var h,c,f=c,_=h+1|0}var E=Wr(r,f);if(0==(0|E))var A=0;else{Se[t>>2]=arguments[Dr.length];var g=E,y=0;r:for(;;){var y,g,m=Ae[a+y|0];do{if(m<<24>>24==0)break r;if(m<<24>>24==37){var S=y+1|0,M=Ae[a+S|0]<<24>>24;if(115==(0|M)){var C=Se[e],R=C,T=C+4|0;Se[e]=T;var O=Se[R>>2];if(0==(0|O)){var N=g,I=S;break}var P=Ca(O);Pa(g,O,P,1);var N=g+P|0,I=S;break}if(99==(0|M)){var D=Se[e],L=D,F=D+4|0;Se[e]=F,Ae[g]=255&Se[L>>2];var N=g+1|0,I=S;break}if(37==(0|M))var X=S;else var X=y;var X;Ae[g]=37;var N=g+1|0,I=X}else{Ae[g]=m;var N=g+1|0,I=y}}while(0);var I,N,g=N,y=I+1|0}Ae[g]=0;var A=E}var A;return Oe=i,A}function Lr(r){var a,a=(r+12|0)>>2,e=Se[a],i=Ae[e];if(i<<24>>24==63){var v=e+1|0;Se[a]=v;var t=1,f=v,_=Ae[v]}else var t=0,f=e,_=i;var _,f,t,s=(_-48&255&255)<9;do if(s){var n=Wr(r,3),o=0!=(0|t);o&&(Ae[n]=45);var l=Ae[Se[a]]+1&255;Ae[n+t|0]=l;var b=o?2:1; -Ae[n+b|0]=0;var k=Se[a]+1|0;Se[a]=k;var u=n}else if(_<<24>>24==57){var c=Wr(r,4),h=0!=(0|t);h&&(Ae[c]=45),Ae[c+t|0]=49;var d=h?2:1;Ae[c+d|0]=48;var w=h?3:2;Ae[c+w|0]=0;var p=Se[a]+1|0;Se[a]=p;var u=c}else{if((_-65&255&255)>=16){var u=0;break}for(var E=0,A=f;;){var A,E,g=A+1|0;Se[a]=g;var y=(Ae[A]<<24>>24)+((E<<4)-65)|0,m=ge[g];if((m-65&255&255)>=16)break;var E=y,A=g}if(m<<24>>24!=64){var u=0;break}var S=Wr(r,17),M=0!=(0|t)?0|He.__str119289:0|ii,C=(za(S,0|He.__str118288,(ne=Oe,Oe+=8,Se[ne>>2]=M,Se[ne+4>>2]=y,ne)),Se[a]+1|0);Se[a]=C;var u=S}while(0);var u;return u}function Fr(r,a,e,i){var v,t,f,_;0==(0|a)&&Xa(0|He.__str72242,212,0|He.___func___str_array_push,0|He.__str115285),0==(0|i)&&Xa(0|He.__str72242,213,0|He.___func___str_array_push,0|He.__str116286);var f=(i+12|0)>>2,s=Me[f],n=0==(0|s);do{if(n){Se[f]=32;var o=Wr(r,128);if(0==(0|o)){var l=0;_=17;break}Se[i+16>>2]=o,_=11;break}if(Me[i+8>>2]>>>0>>0){_=11;break}var b=s<<3,k=Wr(r,b);if(0==(0|k)){var l=0;_=17;break}var u=k,c=i+16|0,h=Se[c>>2],d=Se[f]<<2;Pa(k,h,d,1);var w=Se[f]<<1;Se[f]=w,Se[c>>2]=u,_=11;break}while(0);do if(11==_){if((0|e)==-1)var p=Ca(a),E=p;else var E=e;var E,A=ja(a),g=E+1|0,y=Wr(r,g),t=(i+4|0)>>2,v=(i+16|0)>>2,m=(Se[t]<<2)+Se[v]|0;Se[m>>2]=y;var S=Se[Se[v]+(Se[t]<<2)>>2];if(0==(0|S)){Xa(0|He.__str72242,233,0|He.___func___str_array_push,0|He.__str117287);var M=Se[Se[v]+(Se[t]<<2)>>2]}else var M=S;var M;Pa(M,A,E,1),va(A),Ae[Se[Se[v]+(Se[t]<<2)>>2]+g|0]=0;var C=Se[t]+1|0;Se[t]=C;var R=i+8|0;if(C>>>0>2]>>>0){var l=1;break}Se[R>>2]=C;var l=1}while(0);var l;return l}function Xr(r,a,e,i,v){var t,f,_=Oe;Oe+=28;var s,n=_,o=_+8;Cr(o);var f=(r+12|0)>>2,l=0==(0|e),t=(0|n)>>2,b=n+4|0;r:do if(l)for(;;){var k=Se[f],u=Ae[k];if(u<<24>>24==0){s=12;break r}if(u<<24>>24==64){var c=k;s=7;break r}var h=Pr(r,n,a,1);if(0==(0|h)){var d=0;s=25;break r}var w=Se[t],p=Se[b>>2],E=Dr(r,0|He.__str170,(ne=Oe,Oe+=8,Se[ne>>2]=w,Se[ne+4>>2]=p,ne)),A=Fr(r,E,-1,o);if(0==(0|A)){var d=0;s=25;break r}var g=Se[t],y=Da(g,0|He.__str110280);if(0==(0|y)){s=12;break r}}else for(;;){var m=Se[f],S=Ae[m];if(S<<24>>24==0){s=12;break r}if(S<<24>>24==64){var c=m;s=7;break r}var M=Pr(r,n,a,1);if(0==(0|M)){var d=0;s=25;break r}var C=Se[t],R=Da(C,0|He.__str84254);if(0==(0|R)){s=13;break r}var T=Se[b>>2],O=Dr(r,0|He.__str170,(ne=Oe,Oe+=8,Se[ne>>2]=C,Se[ne+4>>2]=T,ne)),N=Fr(r,O,-1,o);if(0==(0|N)){var d=0;s=25;break r}var I=Se[t],P=Da(I,0|He.__str110280);if(0==(0|P)){s=12;break r}}while(0);do if(7==s){var c;Se[f]=c+1|0,s=12;break}while(0);do if(12==s){if(l){s=14;break}s=13;break}while(0);do if(13==s){var D=Se[f],L=D+1|0;if(Se[f]=L,Ae[D]<<24>>24==90){s=14;break}var d=0;s=25;break}while(0);r:do if(14==s){var F=o+4|0,X=Me[F>>2];do{if(0!=(0|X)){if(1==(0|X)){var j=o+16|0,U=Se[Se[j>>2]>>2],x=Da(U,0|He.__str84254);if(0==(0|x)){s=17;break}var z=j;s=20;break}var V=o+16|0;if(X>>>0<=1){var z=V;s=20;break}for(var B=0,H=1;;){var H,B,K=Se[Se[V>>2]+(H<<2)>>2],Y=Dr(r,0|He.__str112282,(ne=Oe,Oe+=8,Se[ne>>2]=B,Se[ne+4>>2]=K,ne)),G=H+1|0;if(G>>>0>=Me[F>>2]>>>0)break;var B=Y,H=G}if(0==(0|Y)){var z=V;s=20;break}var W=Y,Z=Y;s=21;break}s=17}while(0);if(17==s){var Q=i<<24>>24,q=v<<24>>24,$=Dr(r,0|He.__str111281,(ne=Oe,Oe+=8,Se[ne>>2]=Q,Se[ne+4>>2]=q,ne)),d=$;break}if(20==s)var z,W=Se[Se[z>>2]>>2],Z=0;var Z,W,J=v<<24>>24,rr=v<<24>>24==62;do if(rr){var ar=Ca(W);if(Ae[W+(ar-1)|0]<<24>>24!=62)break;var er=i<<24>>24,ir=Se[Se[o+16>>2]>>2],vr=Dr(r,0|He.__str113283,(ne=Oe,Oe+=16,Se[ne>>2]=er,Se[ne+4>>2]=ir,Se[ne+8>>2]=Z,Se[ne+12>>2]=J,ne)),d=vr;break r}while(0);var tr=i<<24>>24,fr=Se[Se[o+16>>2]>>2],_r=Dr(r,0|He.__str114284,(ne=Oe,Oe+=16,Se[ne>>2]=tr,Se[ne+4>>2]=fr,Se[ne+8>>2]=Z,Se[ne+12>>2]=J,ne)),d=_r}while(0);var d;return Oe=_,d}function jr(r){var a,e=Oe;Oe+=20;var i=e,v=r+24|0,t=Se[v>>2],a=(r+20|0)>>2,f=Se[a],_=r+44|0,s=Se[_>>2];Se[a]=t;var n=Kr(r);if(0==(0|n))var o=0;else{Cr(i);var l=Xr(r,i,0,60,62);if(0==(0|l))var b=n;else var k=Dr(r,0|He.__str170,(ne=Oe,Oe+=8,Se[ne>>2]=n,Se[ne+4>>2]=l,ne)),b=k;var b;Se[v>>2]=t,Se[a]=f,Se[_>>2]=s;var o=b}var o;return Oe=e,o}function Ur(r,a,e,i){var v,t=a>>2;Se[e>>2]=0,Se[t]=0;var f=0==(18&i|0);do{if(f){var _=r<<24>>24,s=1==((_-65)%2|0);if(0==(1&i|0)){if(s?Se[e>>2]=0|He.__str95265:v=14,65==(0|_)||66==(0|_)){Se[t]=0|He.__str96266,v=21;break}if(67==(0|_)||68==(0|_)){Se[t]=0|He.__str97267,v=21;break}if(69==(0|_)||70==(0|_)){Se[t]=0|He.__str98268,v=21;break}if(71==(0|_)||72==(0|_)){Se[t]=0|He.__str99269,v=21;break}if(73==(0|_)||74==(0|_)){Se[t]=0|He.__str100270,v=21;break}if(75==(0|_)||76==(0|_)){v=21;break}if(77==(0|_)){Se[t]=0|He.__str101271,v=21;break}var n=0;v=22;break}if(s?Se[e>>2]=0|He.__str88258:v=5,65==(0|_)||66==(0|_)){Se[t]=0|He.__str89259,v=21;break}if(67==(0|_)||68==(0|_)){Se[t]=0|He.__str90260,v=21;break}if(69==(0|_)||70==(0|_)){Se[t]=0|He.__str91261,v=21;break}if(71==(0|_)||72==(0|_)){Se[t]=0|He.__str92262,v=21;break}if(73==(0|_)||74==(0|_)){Se[t]=0|He.__str93263,v=21;break}if(75==(0|_)||76==(0|_)){v=21;break}if(77==(0|_)){Se[t]=0|He.__str94264,v=21;break}var n=0;v=22;break}v=21}while(0);if(21==v)var n=1;var n;return n}function xr(r,a,e){var i;Se[e>>2]=0;var i=(r+12|0)>>2,v=Se[i];if(Ae[v]<<24>>24==69){Se[e>>2]=0|He.__str102272;var t=Se[i]+1|0;Se[i]=t;var f=t}else var f=v;var f;Se[i]=f+1|0;var _=Ae[f]<<24>>24;if(65==(0|_)){Se[a>>2]=0;var s=1}else if(66==(0|_)){Se[a>>2]=0|He.__str103273;var s=1}else if(67==(0|_)){Se[a>>2]=0|He.__str104274;var s=1}else if(68==(0|_)){Se[a>>2]=0|He.__str105275;var s=1}else var s=0;var s;return s}function zr(r){var a,e,a=(r+12|0)>>2,i=r+40|0,v=r+20|0,t=0|i,f=r+44|0,_=r+48|0,s=r+52|0,n=r+56|0,o=r+20|0,l=r+24|0,b=r+16|0,k=0;r:for(;;){var k,u=Se[a],c=Ae[u];if(c<<24>>24==64){var h=u+1|0;Se[a]=h;var d=1;break}var w=c<<24>>24;do{if(0==(0|w)){var d=0;break r}if(48==(0|w)||49==(0|w)||50==(0|w)||51==(0|w)||52==(0|w)||53==(0|w)||54==(0|w)||55==(0|w)||56==(0|w)||57==(0|w)){var p=u+1|0;Se[a]=p;var E=(Ae[u]<<24>>24)-48|0,A=Yr(v,E),g=A;e=14;break}if(63==(0|w)){var y=u+1|0;Se[a]=y;var m=Ae[y]<<24>>24;if(36==(0|m)){var S=u+2|0;Se[a]=S;var M=jr(r);if(0==(0|M)){var d=0;break r}var C=Fr(r,M,-1,v);if(0==(0|C)){var d=0;break r}var R=M;e=15;break}if(63==(0|m)){var T=Se[t>>2],O=Se[f>>2],N=Se[_>>2],I=Se[s>>2],P=Se[n>>2],D=Se[o>>2],L=Se[l>>2];Cr(i);var F=Ir(r);if(0==(0|F))var X=k;else var j=Se[b>>2],U=Dr(r,0|He.__str109279,(ne=Oe,Oe+=4,Se[ne>>2]=j,ne)),X=U;var X;Se[o>>2]=D,Se[l>>2]=L,Se[t>>2]=T,Se[f>>2]=O,Se[_>>2]=N,Se[s>>2]=I,Se[n>>2]=P;var g=X;e=14;break}var x=Lr(r);if(0==(0|x)){var d=0;break r}var z=Dr(r,0|He.__str109279,(ne=Oe,Oe+=4,Se[ne>>2]=x,ne)),g=z;e=14;break}var V=Kr(r),g=V;e=14;break}while(0);if(14==e){var g;if(0==(0|g)){var d=0;break}var R=g}var R,B=Fr(r,R,-1,i);if(0==(0|B)){var d=0;break}var k=R}var d;return d}function Vr(r){var a,e,i,v=Oe;Oe+=36;var t,f=v,i=f>>2,_=v+4,s=v+8,e=s>>2,n=v+16;Se[i]=0;var o=0|r,l=Se[o>>2],b=0==(128&l|0),k=r+12|0;do if(b){var u=Ae[Se[k>>2]]<<24>>24;if(48==(0|u))var c=0|He.__str76246,h=k,a=h>>2;else if(49==(0|u))var c=0|He.__str77247,h=k,a=h>>2;else{if(50!=(0|u)){var c=0,h=k,a=h>>2;break}var c=0|He.__str78248,h=k,a=h>>2}}else var c=0,h=k,a=h>>2;while(0);var h,c,d=0==(512&l|0);do if(d){if((Ae[Se[a]]-48&255&255)>=3){var w=0;break}var w=0|He.__str79249}else var w=0;while(0);var w,p=Gr(r,0),E=Se[a],A=E+1|0;Se[a]=A;var g=Ae[E]<<24>>24;do{if(48==(0|g)||49==(0|g)||50==(0|g)||51==(0|g)||52==(0|g)||53==(0|g)){var y=r+44|0,m=Se[y>>2];Cr(n);var S=Pr(r,s,n,0);if(0==(0|S)){var M=0;t=28;break}var C=xr(r,f,_);if(0==(0|C)){var M=0;t=28;break}var R=Se[i],T=0==(0|R),O=Se[_>>2];do if(T)Se[i]=O;else{if(0==(0|O))break;var N=Dr(r,0|He.__str83253,(ne=Oe,Oe+=8,Se[ne>>2]=R,Se[ne+4>>2]=O,ne));Se[i]=N}while(0);Se[y>>2]=m,t=22;break}if(54==(0|g)||55==(0|g)){var I=s+4|0;Se[I>>2]=0,Se[e]=0;var P=xr(r,f,_);if(0==(0|P)){var M=0;t=28;break}if(Ae[Se[a]]<<24>>24==64){t=22;break}var D=qr(r);if(0==(0|D)){var M=0;t=28;break}var L=Dr(r,0|He.__str107277,(ne=Oe,Oe+=4,Se[ne>>2]=D,ne));Se[I>>2]=L,t=22;break}if(56==(0|g)||57==(0|g)){Se[e+1]=0,Se[e]=0,Se[i]=0,t=22;break}var M=0;t=28}while(0);if(22==t){var F=0==(4096&Se[o>>2]|0);do{if(F){var X=Se[e],j=Se[i];if(0==(0|j)){var U=X;t=26;break}var x=0!=(0|X)?0|He.__str87257:0,z=0|He.__str87257,V=j,B=x,H=X;t=27;break}Se[i]=0,Se[e+1]=0,Se[e]=0;var U=0;t=26;break}while(0);if(26==t)var U,K=0!=(0|U)?0|He.__str87257:0,z=K,V=0,B=0,H=U;var H,B,V,z,Y=Se[e+1],G=Dr(r,0|He.__str108278,(ne=Oe,Oe+=32,Se[ne>>2]=c,Se[ne+4>>2]=w,Se[ne+8>>2]=H,Se[ne+12>>2]=B,Se[ne+16>>2]=V,Se[ne+20>>2]=z,Se[ne+24>>2]=p,Se[ne+28>>2]=Y,ne));Se[r+16>>2]=G;var M=1}var M;return Oe=v,M}function Br(r,a){var e,i,v,t,f=Oe;Oe+=44;var _,s=f,t=s>>2,n=f+8,o=f+12,v=o>>2,l=f+16,b=f+20,k=f+40;Se[v]=0;var i=(r+12|0)>>2,u=Se[i],c=u+1|0;Se[i]=c;var h=ge[u],d=h<<24>>24,w=(h-65&255&255)>25;r:do if(w)var p=0;else{var e=(0|r)>>2,E=Me[e],A=0==(128&E|0),g=d-65|0;do if(A){var y=g/8|0;if(0==(0|y))var m=0|He.__str76246,S=g;else if(1==(0|y))var m=0|He.__str77247,S=g;else{if(2!=(0|y)){var m=0,S=g;break}var m=0|He.__str78248,S=g}}else var m=0,S=g;while(0);var S,m,M=0==(512&E|0)&h<<24>>24<89,C=(0|S)%8;do if(M)if(2==(0|C)||3==(0|C))var R=m,T=0|He.__str79249;else if(4==(0|C)||5==(0|C))var R=m,T=0|He.__str80250;else{if(6!=(0|C)&&7!=(0|C)){var R=m,T=0;break}var O=Dr(r,0|He.__str81251,(ne=Oe,Oe+=4,Se[ne>>2]=m,ne)),R=O,T=0|He.__str80250}else var R=m,T=0;while(0);var T,R,N=Gr(r,0),I=6==(0|C);do{if(!I){if(7==((d-56)%8|0)){_=14;break}var P=N;_=15;break}_=14}while(0);if(14==_)var D=Lr(r),L=Dr(r,0|He.__str82252,(ne=Oe,Oe+=8,Se[ne>>2]=N,Se[ne+4>>2]=D,ne)),P=L;var P,F=h<<24>>24>88;do if(F)var X=0;else{if((C-2|0)>>>0<2){var X=0;break}var j=xr(r,o,k);if(0==(0|j)){var p=0;break r}var U=Me[v],x=Se[k>>2];if(0==(0|U)&0==(0|x)){var X=0;break}var z=Dr(r,0|He.__str83253,(ne=Oe,Oe+=8,Se[ne>>2]=U,Se[ne+4>>2]=x,ne));Se[v]=z;var X=z}while(0);var X,V=Se[i],B=V+1|0;Se[i]=B;var H=Ae[V],K=Se[e],Y=Ur(H,n,l,K);if(0==(0|Y)){var p=0;break}Cr(b);var G=Se[i];if(Ae[G]<<24>>24==64){Se[t]=0|He.__str84254,Se[t+1]=0;var W=G+1|0;Se[i]=W}else{var Z=Pr(r,s,b,0);if(0==(0|Z)){var p=0;break}}if(0!=(4&Se[e]|0)&&(Se[t+1]=0,Se[t]=0),0==(0|a))var Q=P;else{var q=0|s,$=Se[q>>2],J=s+4|0,rr=Se[J>>2],ar=Dr(r,0|He.__str85255,(ne=Oe,Oe+=12,Se[ne>>2]=P,Se[ne+4>>2]=$,Se[ne+8>>2]=rr,ne));Se[J>>2]=0,Se[q>>2]=0;var Q=ar}var Q,er=r+44|0,ir=Se[er>>2],vr=Xr(r,b,1,40,41);if(0==(0|vr)){var p=0;break}if(0==(4096&Se[e]|0))var tr=vr,fr=X;else{Se[v]=0;var tr=0,fr=0}var fr,tr;Se[er>>2]=ir;var _r=Se[t],sr=Se[t+1];if(0==(0|_r))var nr=0;else var or=0!=(0|sr)?0:0|He.__str87257,nr=or;var nr,lr=Se[n>>2],br=0!=(0|lr)?0|He.__str87257:0,kr=Se[l>>2],ur=Dr(r,0|He.__str86256,(ne=Oe,Oe+=44,Se[ne>>2]=R,Se[ne+4>>2]=T,Se[ne+8>>2]=_r,Se[ne+12>>2]=nr,Se[ne+16>>2]=lr,Se[ne+20>>2]=br,Se[ne+24>>2]=kr,Se[ne+28>>2]=Q,Se[ne+32>>2]=tr,Se[ne+36>>2]=fr,Se[ne+40>>2]=sr,ne));Se[r+16>>2]=ur;var p=1}while(0);var p;return Oe=f,p}function Hr(r){var a,a=(r+12|0)>>2,e=Se[a];if(Ae[e]<<24>>24==36)var i=e;else{Xa(0|He.__str72242,1252,0|He.___func___handle_template,0|He.__str74244);var i=Se[a]}var i;Se[a]=i+1|0;var v=Kr(r),t=0==(0|v);do if(t)var f=0;else{var _=Xr(r,0,0,60,62);if(0==(0|_)){var f=0;break}var s=Dr(r,0|He.__str170,(ne=Oe,Oe+=8,Se[ne>>2]=v,Se[ne+4>>2]=_,ne));Se[r+16>>2]=s;var f=1}while(0);var f;return f}function Kr(r){for(var a,a=(r+12|0)>>2,e=Me[a],i=e,v=Ae[e];;){var v,i;if(!((v-65&255&255)<26|(v-97&255&255)<26|(v-48&255&255)<10)&&v<<24>>24!=95&&v<<24>>24!=36){var t=0;break}var f=i+1|0;Se[a]=f;var _=ge[f];if(_<<24>>24==64){Se[a]=i+2|0;var s=f-e|0,n=r+20|0,o=Fr(r,e,s,n);if(0==(0|o)){var t=0;break}var l=Se[r+24>>2]-1-Se[n>>2]|0,b=Yr(n,l),t=b;break}var i=f,v=_}var t;return t}function Yr(r,a){0==(0|r)&&Xa(0|He.__str72242,263,0|He.___func___str_array_get_ref,0|He.__str75245);var e=Se[r>>2]+a|0;if(e>>>0>2]>>>0)var i=Se[Se[r+16>>2]+(e<<2)>>2];else var i=0;var i;return i}function Gr(r,a){var e,e=(r+44|0)>>2,i=Me[e];if(i>>>0>a>>>0){for(var v=r+56|0,t=a,f=0,_=Se[v>>2],s=i;;){var s,_,f,t,n=Me[_+(t<<2)>>2];if(0==(0|n)){Xa(0|He.__str72242,680,0|He.___func___get_class_string,0|He.__str106276);var o=Se[v>>2],l=o,b=Se[o+(t<<2)>>2],k=Se[e]}else var l=_,b=n,k=s;var k,b,l,u=Ca(b),c=u+(f+2)|0,h=t+1|0;if(h>>>0>=k>>>0)break;var t=h,f=c,_=l,s=k}var d=c-1|0}else var d=-1;var d,w=Wr(r,d);if(0==(0|w))var p=0;else{var E=Se[e]-1|0,A=(0|E)<(0|a);r:do if(A)var g=0;else for(var y=r+56|0,m=0,S=E;;){var S,m,M=Se[Se[y>>2]+(S<<2)>>2],C=Ca(M),R=w+m|0;Pa(R,M,C,1);var T=C+m|0;if((0|S)>(0|a)){var O=T+1|0;Ae[w+T|0]=58;var N=T+2|0;Ae[w+O|0]=58;var I=N}else var I=T;var I,P=S-1|0;if((0|P)<(0|a)){var g=I;break r}var m=I,S=P}while(0);var g;Ae[w+g|0]=0;var p=w}var p;return p}function Wr(r,a){var e,i=a>>>0>1020;do if(i){var v=Se[r+4>>2],t=a+4|0,f=pe[v](t);if(0==(0|f)){var _=0;break}var s=r+60|0,n=Se[s>>2],o=f;Se[o>>2]=n,Se[s>>2]=f,Se[r+64>>2]=0;var _=f+4|0}else{var e=(r+64|0)>>2,l=Me[e];if(l>>>0>>0){var b=Se[r+4>>2],k=pe[b](1024);if(0==(0|k)){var _=0;break}var u=r+60|0,c=Se[u>>2],h=k;Se[h>>2]=c,Se[u>>2]=k,Se[e]=1020;var d=1020,w=k}else var d=l,w=Se[r+60>>2];var w,d;Se[e]=d-a|0;var _=w+(1024-d)|0}while(0);var _;return _}function Zr(r){var a=r<<24>>24;if(68==(0|a))var e=0|He.__str157327;else if(69==(0|a))var e=0|He.__str158328;else if(70==(0|a))var e=0|He.__str159329;else if(71==(0|a))var e=0|He.__str160330;else if(72==(0|a))var e=0|He.__str161331;else if(73==(0|a))var e=0|He.__str162332;else if(74==(0|a))var e=0|He.__str163333;else if(75==(0|a))var e=0|He.__str164334;else if(76==(0|a))var e=0|He.__str165335;else if(77==(0|a))var e=0|He.__str166336;else if(78==(0|a))var e=0|He.__str167337;else if(87==(0|a))var e=0|He.__str168338;else var e=0;var e;return e}function Qr(r){var a=r<<24>>24;if(67==(0|a))var e=0|He.__str145315;else if(68==(0|a))var e=0|He.__str146316;else if(69==(0|a))var e=0|He.__str147317;else if(70==(0|a))var e=0|He.__str148318;else if(71==(0|a))var e=0|He.__str149319;else if(72==(0|a))var e=0|He.__str150320;else if(73==(0|a))var e=0|He.__str151321;else if(74==(0|a))var e=0|He.__str152322;else if(75==(0|a))var e=0|He.__str153323;else if(77==(0|a))var e=0|He.__str154324;else if(78==(0|a))var e=0|He.__str155325;else if(79==(0|a))var e=0|He.__str156326;else if(88==(0|a))var e=0|He.__str84254;else if(90==(0|a))var e=0|He.__str110280;else var e=0;var e;return e}function qr(r){var a=r+44|0,e=Se[a>>2],i=zr(r);if(0==(0|i))var v=0;else var t=Gr(r,e),v=t;var v;return Se[a>>2]=e,v}function $r(r,a,e,i,v){var t,f,_,s=Oe;Oe+=16;var n,o=s,_=o>>2,l=s+4,b=s+8,f=b>>2;Se[l>>2]=0|ii;var t=(a+12|0)>>2,k=Se[t];if(Ae[k]<<24>>24==69){Se[l>>2]=0|He.__str134304;var u=k+1|0;Se[t]=u;var c=0|He.__str134304}else var c=0|ii;var c,h=i<<24>>24;do{if(65==(0|h)){var d=Dr(a,0|He.__str135305,(ne=Oe,Oe+=4,Se[ne>>2]=c,ne)),w=d;n=10;break}if(66==(0|h)){var p=Dr(a,0|He.__str136306,(ne=Oe,Oe+=4,Se[ne>>2]=c,ne)),w=p;n=10;break}if(80==(0|h)){var E=Dr(a,0|He.__str137307,(ne=Oe,Oe+=4,Se[ne>>2]=c,ne)),w=E;n=10;break}if(81==(0|h)){var A=Dr(a,0|He.__str138308,(ne=Oe,Oe+=4,Se[ne>>2]=c,ne)),w=A;n=10;break}if(82==(0|h)){var g=Dr(a,0|He.__str139309,(ne=Oe,Oe+=4,Se[ne>>2]=c,ne)),w=g;n=10;break}if(83==(0|h)){var y=Dr(a,0|He.__str140310,(ne=Oe,Oe+=4,Se[ne>>2]=c,ne)),w=y;n=10;break}if(63==(0|h)){var w=0|ii;n=10}else n=31}while(0);r:do if(10==n){var w,m=xr(a,o,l);if(0==(0|m))break;var S=a+44|0,M=Se[S>>2],C=Se[t],R=Ae[C]<<24>>24==89;a:do if(R){var T=C+1|0;Se[t]=T;var O=Lr(a);if(0==(0|O))break r;var N=Ha(O),I=Ae[w]<<24>>24==32,P=Se[_],D=0==(0|P);do{if(I){if(!D){n=17;break}var L=w+1|0;n=18;break}if(D){var L=w;n=18;break}n=17;break}while(0);if(17==n){var F=Dr(a,0|He.__str141311,(ne=Oe,Oe+=8,Se[ne>>2]=P,Se[ne+4>>2]=w,ne));Se[_]=0;var X=F}else if(18==n)var L,j=Dr(a,0|He.__str142312,(ne=Oe,Oe+=4,Se[ne>>2]=L,ne)),X=j;var X;if(0==(0|N)){var U=X;break}for(var x=X,z=N;;){var z,x,V=z-1|0,B=Lr(a),H=Dr(a,0|He.__str143313,(ne=Oe,Oe+=8,Se[ne>>2]=x,Se[ne+4>>2]=B,ne));if(0==(0|V)){var U=H;break a}var x=H,z=V}}else var U=w;while(0);var U,K=Pr(a,b,e,0);if(0==(0|K))break;var Y=Se[_];if(0==(0|Y)){var G=0==(0|v);do if(G){if(Ae[U]<<24>>24==0){var W=U;break}var Z=U+1|0;if(Ae[Z]<<24>>24!=42){var W=U;break}var Q=Se[f],q=Ca(Q);if(Ae[Q+(q-1)|0]<<24>>24!=42){var W=U;break}var W=Z}else var W=U;while(0);var W,$=Se[f],J=Dr(a,0|He.__str170,(ne=Oe,Oe+=8,Se[ne>>2]=$,Se[ne+4>>2]=W,ne));Se[r>>2]=J}else{var rr=Se[f],ar=Dr(a,0|He.__str144314,(ne=Oe,Oe+=12,Se[ne>>2]=rr,Se[ne+4>>2]=Y,Se[ne+8>>2]=U,ne));Se[r>>2]=ar}var er=Se[f+1];Se[r+4>>2]=er,Se[S>>2]=M}while(0);Oe=s}function Jr(r){var a,e=r>>>0<245;do{if(e){if(r>>>0<11)var i=16;else var i=r+11&-8;var i,v=i>>>3,t=Me[vi>>2],f=t>>>(v>>>0);if(0!=(3&f|0)){var _=(1&f^1)+v|0,s=_<<1,n=(s<<2)+vi+40|0,o=(s+2<<2)+vi+40|0,l=Me[o>>2],b=l+8|0,k=Me[b>>2];if((0|n)==(0|k))Se[vi>>2]=t&(1<<_^-1);else{if(k>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";Se[o>>2]=k,Se[k+12>>2]=n}var u=_<<3;Se[l+4>>2]=3|u;var c=l+(4|u)|0,h=1|Se[c>>2];Se[c>>2]=h;var d=b;a=38;break}if(i>>>0<=Me[vi+8>>2]>>>0){var w=i;a=30;break}if(0!=(0|f)){var p=2<>>12&16,y=A>>>(g>>>0),m=y>>>5&8,S=y>>>(m>>>0),M=S>>>2&4,C=S>>>(M>>>0),R=C>>>1&2,T=C>>>(R>>>0),O=T>>>1&1,N=(m|g|M|R|O)+(T>>>(O>>>0))|0,I=N<<1,P=(I<<2)+vi+40|0,D=(I+2<<2)+vi+40|0,L=Me[D>>2],F=L+8|0,X=Me[F>>2];if((0|P)==(0|X))Se[vi>>2]=t&(1<>>0>2]>>>0)throw Ka(),"Reached an unreachable!";Se[D>>2]=X,Se[X+12>>2]=P}var j=N<<3,U=j-i|0;Se[L+4>>2]=3|i;var x=L,z=x+i|0;Se[x+(4|i)>>2]=1|U,Se[x+j>>2]=U;var V=Me[vi+8>>2];if(0!=(0|V)){var B=Se[vi+20>>2],H=V>>>2&1073741822,K=(H<<2)+vi+40|0,Y=Me[vi>>2],G=1<<(V>>>3),W=0==(Y&G|0);do{if(!W){var Z=(H+2<<2)+vi+40|0,Q=Me[Z>>2];if(Q>>>0>=Me[vi+16>>2]>>>0){var q=Q,$=Z;break}throw Ka(),"Reached an unreachable!"}Se[vi>>2]=Y|G;var q=K,$=(H+2<<2)+vi+40|0}while(0);var $,q;Se[$>>2]=B,Se[q+12>>2]=B;var J=B+8|0;Se[J>>2]=q;var rr=B+12|0;Se[rr>>2]=K}Se[vi+8>>2]=U,Se[vi+20>>2]=z;var d=F;a=38;break}if(0==(0|Se[vi+4>>2])){var w=i;a=30;break}var ar=ra(i);if(0==(0|ar)){var w=i;a=30;break}var d=ar;a=38;break}if(r>>>0>4294967231){var w=-1;a=30;break}var er=r+11&-8;if(0==(0|Se[vi+4>>2])){var w=er;a=30;break}var ir=ea(er);if(0==(0|ir)){var w=er;a=30;break}var d=ir;a=38;break}while(0);if(30==a){var w,vr=Me[vi+8>>2];if(w>>>0>vr>>>0){var tr=Me[vi+12>>2];if(w>>>0>>0){var fr=tr-w|0;Se[vi+12>>2]=fr;var _r=Me[vi+24>>2],sr=_r;Se[vi+24>>2]=sr+w|0,Se[w+(sr+4)>>2]=1|fr,Se[_r+4>>2]=3|w;var d=_r+8|0}else var nr=aa(w),d=nr}else{var or=vr-w|0,lr=Me[vi+20>>2];if(or>>>0>15){var br=lr;Se[vi+20>>2]=br+w|0,Se[vi+8>>2]=or,Se[w+(br+4)>>2]=1|or,Se[br+vr>>2]=or,Se[lr+4>>2]=3|w}else{Se[vi+8>>2]=0,Se[vi+20>>2]=0,Se[lr+4>>2]=3|vr;var kr=vr+(lr+4)|0,ur=1|Se[kr>>2];Se[kr>>2]=ur}var d=lr+8|0}}var d;return d}function ra(r){var a,e,i,v=Se[vi+4>>2],t=(v&-v)-1|0,f=t>>>12&16,_=t>>>(f>>>0),s=_>>>5&8,n=_>>>(s>>>0),o=n>>>2&4,l=n>>>(o>>>0),b=l>>>1&2,k=l>>>(b>>>0),u=k>>>1&1,c=Me[vi+((s|f|o|b|u)+(k>>>(u>>>0))<<2)+304>>2],h=c,e=h>>2,d=(Se[c+4>>2]&-8)-r|0;r:for(;;)for(var d,h,w=h;;){var w,p=Se[w+16>>2];if(0==(0|p)){var E=Se[w+20>>2];if(0==(0|E))break r;var A=E}else var A=p;var A,g=(Se[A+4>>2]&-8)-r|0;if(g>>>0>>0){var h=A,e=h>>2,d=g;continue r}var w=A}var y=h,m=Me[vi+16>>2],S=y>>>0>>0;do if(!S){var M=y+r|0,C=M;if(y>>>0>=M>>>0)break;var R=Me[e+6],T=Me[e+3],O=(0|T)==(0|h);do if(O){var N=h+20|0,I=Se[N>>2];if(0==(0|I)){var P=h+16|0,D=Se[P>>2];if(0==(0|D)){var L=0,a=L>>2;break}var F=P,X=D}else{var F=N,X=I;i=14}for(;;){var X,F,j=X+20|0,U=Se[j>>2];if(0==(0|U)){var x=X+16|0,z=Me[x>>2];if(0==(0|z))break;var F=x,X=z}else var F=j,X=U}if(F>>>0>>0)throw Ka(),"Reached an unreachable!";Se[F>>2]=0;var L=X,a=L>>2}else{var V=Me[e+2];if(V>>>0>>0)throw Ka(),"Reached an unreachable!";Se[V+12>>2]=T,Se[T+8>>2]=V;var L=T,a=L>>2}while(0);var L,B=0==(0|R);r:do if(!B){var H=h+28|0,K=(Se[H>>2]<<2)+vi+304|0,Y=(0|h)==(0|Se[K>>2]);do{if(Y){if(Se[K>>2]=L,0!=(0|L))break;var G=Se[vi+4>>2]&(1<>2]^-1);Se[vi+4>>2]=G;break r}if(R>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";var W=R+16|0;if((0|Se[W>>2])==(0|h)?Se[W>>2]=L:Se[R+20>>2]=L,0==(0|L))break r}while(0);if(L>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";Se[a+6]=R;var Z=Me[e+4];if(0!=(0|Z)){if(Z>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";Se[a+4]=Z,Se[Z+24>>2]=L}var Q=Me[e+5];if(0==(0|Q))break;if(Q>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";Se[a+5]=Q,Se[Q+24>>2]=L}while(0);if(d>>>0<16){var q=d+r|0;Se[e+1]=3|q;var $=q+(y+4)|0,J=1|Se[$>>2];Se[$>>2]=J}else{Se[e+1]=3|r,Se[r+(y+4)>>2]=1|d,Se[y+d+r>>2]=d;var rr=Me[vi+8>>2];if(0!=(0|rr)){var ar=Me[vi+20>>2],er=rr>>>2&1073741822,ir=(er<<2)+vi+40|0,vr=Me[vi>>2],tr=1<<(rr>>>3),fr=0==(vr&tr|0);do{if(!fr){var _r=(er+2<<2)+vi+40|0,sr=Me[_r>>2];if(sr>>>0>=Me[vi+16>>2]>>>0){var nr=sr,or=_r;break}throw Ka(),"Reached an unreachable!"}Se[vi>>2]=vr|tr;var nr=ir,or=(er+2<<2)+vi+40|0}while(0);var or,nr;Se[or>>2]=ar,Se[nr+12>>2]=ar,Se[ar+8>>2]=nr,Se[ar+12>>2]=ir}Se[vi+8>>2]=d,Se[vi+20>>2]=C}return h+8|0}while(0);throw Ka(),"Reached an unreachable!"}function aa(r){var a,e;0==(0|Se[ti>>2])&&ba();var i=0==(4&Se[vi+440>>2]|0);do{if(i){var v=Se[vi+24>>2],t=0==(0|v);do{if(!t){var f=v,_=ua(f);if(0==(0|_)){e=6;break}var s=Se[ti+8>>2],n=r+47-Se[vi+12>>2]+s&-s;if(n>>>0>=2147483647){e=14;break}var o=re(n);if((0|o)==(Se[_>>2]+Se[_+4>>2]|0)){var l=o,b=n,k=o;e=13;break}var u=o,c=n;e=15;break}e=6}while(0);do if(6==e){var h=re(0);if((0|h)==-1){e=14;break}var d=Se[ti+8>>2],w=d+(r+47)&-d,p=h,E=Se[ti+4>>2],A=E-1|0;if(0==(A&p|0))var g=w;else var g=w-p+(A+p&-E)|0;var g;if(g>>>0>=2147483647){e=14;break}var y=re(g);if((0|y)==(0|h)){var l=h,b=g,k=y;e=13;break}var u=y,c=g;e=15;break}while(0);if(13==e){var k,b,l;if((0|l)!=-1){var m=b,S=l;e=26;break}var u=k,c=b}else if(14==e){var M=4|Se[vi+440>>2];Se[vi+440>>2]=M,e=23;break}var c,u,C=0|-c,R=(0|u)!=-1&c>>>0<2147483647;do{if(R){if(c>>>0>=(r+48|0)>>>0){var T=c;e=21;break}var O=Se[ti+8>>2],N=r+47-c+O&-O;if(N>>>0>=2147483647){var T=c;e=21;break}var I=re(N);if((0|I)==-1){re(C);e=22;break}var T=N+c|0;e=21;break}var T=c;e=21}while(0);if(21==e){var T;if((0|u)!=-1){var m=T,S=u;e=26;break}}var P=4|Se[vi+440>>2];Se[vi+440>>2]=P,e=23;break}e=23}while(0);do if(23==e){var D=Se[ti+8>>2],L=D+(r+47)&-D;if(L>>>0>=2147483647){e=49;break}var F=re(L),X=re(0);if(!((0|X)!=-1&(0|F)!=-1&F>>>0>>0)){e=49;break}var j=X-F|0;if(j>>>0<=(r+40|0)>>>0|(0|F)==-1){e=49;break}var m=j,S=F;e=26;break}while(0);r:do if(26==e){var S,m,U=Se[vi+432>>2]+m|0;Se[vi+432>>2]=U,U>>>0>Me[vi+436>>2]>>>0&&(Se[vi+436>>2]=U);var x=Me[vi+24>>2],z=0==(0|x);a:do if(z){var V=Me[vi+16>>2];0==(0|V)|S>>>0>>0&&(Se[vi+16>>2]=S),Se[vi+444>>2]=S,Se[vi+448>>2]=m,Se[vi+456>>2]=0;var B=Se[ti>>2];Se[vi+36>>2]=B,Se[vi+32>>2]=-1,ha(),ca(S,m-40|0)}else{for(var H=vi+444|0,a=H>>2;;){var H;if(0==(0|H))break;var K=Me[a],Y=H+4|0,G=Me[Y>>2],W=K+G|0;if((0|S)==(0|W)){if(0!=(8&Se[a+3]|0))break;var Z=x;if(!(Z>>>0>=K>>>0&Z>>>0>>0))break;Se[Y>>2]=G+m|0;var Q=Se[vi+24>>2],q=Se[vi+12>>2]+m|0;ca(Q,q);break a}var H=Se[a+2],a=H>>2}S>>>0>2]>>>0&&(Se[vi+16>>2]=S);for(var $=S+m|0,J=vi+444|0;;){var J;if(0==(0|J))break;var rr=0|J,ar=Me[rr>>2];if((0|ar)==(0|$)){if(0!=(8&Se[J+12>>2]|0))break;Se[rr>>2]=S;var er=J+4|0,ir=Se[er>>2]+m|0;Se[er>>2]=ir;var vr=da(S,ar,r),tr=vr;e=50;break r}var J=Se[J+8>>2]}Ma(S,m)}while(0);var fr=Me[vi+12>>2];if(fr>>>0<=r>>>0){e=49;break}var _r=fr-r|0;Se[vi+12>>2]=_r;var sr=Me[vi+24>>2],nr=sr;Se[vi+24>>2]=nr+r|0,Se[r+(nr+4)>>2]=1|_r,Se[sr+4>>2]=3|r;var tr=sr+8|0;e=50;break}while(0);if(49==e){var or=Je();Se[or>>2]=12;var tr=0}var tr;return tr}function ea(r){var a,e,i,v,t,f,_=r>>2,s=0|-r,n=r>>>8,o=0==(0|n);do if(o)var l=0;else{if(r>>>0>16777215){var l=31;break}var b=(n+1048320|0)>>>16&8,k=n<>>16&4,c=k<>>16&2,d=14-(u|b|h)+(c<>>15)|0,l=r>>>((d+7|0)>>>0)&1|d<<1}while(0);var l,w=Me[vi+(l<<2)+304>>2],p=0==(0|w);r:do if(p)var E=0,A=s,g=0;else{if(31==(0|l))var y=0;else var y=25-(l>>>1)|0;for(var y,m=0,S=s,M=w,t=M>>2,C=r<>>0>>0){if((0|T)==(0|r)){var E=M,A=O,g=M;break r}var N=M,I=O}else var N=m,I=S;var I,N,P=Me[t+5],D=Me[((C>>>31<<2)+16>>2)+t],L=0==(0|P)|(0|P)==(0|D)?R:P;if(0==(0|D)){var E=N,A=I,g=L;break r}var m=N,S=I,M=D,t=M>>2,C=C<<1,R=L}}while(0);var g,A,E,F=0==(0|g)&0==(0|E);do if(F){var X=2<>2]&(X|-X);if(0==(0|j)){var U=g;break}var x=(j&-j)-1|0,z=x>>>12&16,V=x>>>(z>>>0),B=V>>>5&8,H=V>>>(B>>>0),K=H>>>2&4,Y=H>>>(K>>>0),G=Y>>>1&2,W=Y>>>(G>>>0),Z=W>>>1&1,U=Se[vi+((B|z|K|G|Z)+(W>>>(Z>>>0))<<2)+304>>2]}else var U=g;while(0);var U,Q=0==(0|U);r:do if(Q)var q=A,$=E,v=$>>2;else for(var J=U,i=J>>2,rr=A,ar=E;;){var ar,rr,J,er=(Se[i+1]&-8)-r|0,ir=er>>>0>>0,vr=ir?er:rr,tr=ir?J:ar,fr=Me[i+4];if(0==(0|fr)){var _r=Me[i+5];if(0==(0|_r)){var q=vr,$=tr,v=$>>2;break r}var J=_r,i=J>>2,rr=vr,ar=tr}else var J=fr,i=J>>2,rr=vr,ar=tr}while(0);var $,q,sr=0==(0|$);r:do{if(!sr){if(q>>>0>=(Se[vi+8>>2]-r|0)>>>0){var nr=0;break}var or=$,e=or>>2,lr=Me[vi+16>>2],br=or>>>0>>0;do if(!br){var kr=or+r|0,ur=kr;if(or>>>0>=kr>>>0)break;var cr=Me[v+6],hr=Me[v+3],dr=(0|hr)==(0|$);do if(dr){var wr=$+20|0,pr=Se[wr>>2];if(0==(0|pr)){var Er=$+16|0,Ar=Se[Er>>2];if(0==(0|Ar)){var gr=0,a=gr>>2;break}var yr=Er,mr=Ar}else{var yr=wr,mr=pr;f=28}for(;;){var mr,yr,Sr=mr+20|0,Mr=Se[Sr>>2];if(0==(0|Mr)){var Cr=mr+16|0,Rr=Me[Cr>>2];if(0==(0|Rr))break;var yr=Cr,mr=Rr}else var yr=Sr,mr=Mr}if(yr>>>0>>0)throw Ka(),"Reached an unreachable!";Se[yr>>2]=0;var gr=mr,a=gr>>2}else{var Tr=Me[v+2];if(Tr>>>0>>0)throw Ka(),"Reached an unreachable!";Se[Tr+12>>2]=hr,Se[hr+8>>2]=Tr;var gr=hr,a=gr>>2}while(0);var gr,Or=0==(0|cr);a:do if(!Or){var Nr=$+28|0,Ir=(Se[Nr>>2]<<2)+vi+304|0,Pr=(0|$)==(0|Se[Ir>>2]);do{if(Pr){if(Se[Ir>>2]=gr,0!=(0|gr))break;var Dr=Se[vi+4>>2]&(1<>2]^-1);Se[vi+4>>2]=Dr;break a}if(cr>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";var Lr=cr+16|0;if((0|Se[Lr>>2])==(0|$)?Se[Lr>>2]=gr:Se[cr+20>>2]=gr,0==(0|gr))break a}while(0);if(gr>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";Se[a+6]=cr;var Fr=Me[v+4];if(0!=(0|Fr)){if(Fr>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";Se[a+4]=Fr,Se[Fr+24>>2]=gr}var Xr=Me[v+5];if(0==(0|Xr))break;if(Xr>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";Se[a+5]=Xr,Se[Xr+24>>2]=gr}while(0);var jr=q>>>0<16;a:do if(jr){var Ur=q+r|0;Se[v+1]=3|Ur;var xr=Ur+(or+4)|0,zr=1|Se[xr>>2];Se[xr>>2]=zr}else if(Se[v+1]=3|r,Se[_+(e+1)]=1|q,Se[(q>>2)+e+_]=q,q>>>0<256){var Vr=q>>>2&1073741822,Br=(Vr<<2)+vi+40|0,Hr=Me[vi>>2],Kr=1<<(q>>>3),Yr=0==(Hr&Kr|0);do{if(!Yr){var Gr=(Vr+2<<2)+vi+40|0,Wr=Me[Gr>>2];if(Wr>>>0>=Me[vi+16>>2]>>>0){var Zr=Wr,Qr=Gr;break}throw Ka(),"Reached an unreachable!"}Se[vi>>2]=Hr|Kr;var Zr=Br,Qr=(Vr+2<<2)+vi+40|0}while(0);var Qr,Zr;Se[Qr>>2]=ur,Se[Zr+12>>2]=ur,Se[_+(e+2)]=Zr,Se[_+(e+3)]=Br}else{var qr=kr,$r=q>>>8,Jr=0==(0|$r);do if(Jr)var ra=0;else{if(q>>>0>16777215){var ra=31;break}var aa=($r+1048320|0)>>>16&8,ea=$r<>>16&4,va=ea<>>16&2,fa=14-(ia|aa|ta)+(va<>>15)|0,ra=q>>>((fa+7|0)>>>0)&1|fa<<1}while(0);var ra,_a=(ra<<2)+vi+304|0;Se[_+(e+7)]=ra;var sa=r+(or+16)|0;Se[_+(e+5)]=0,Se[sa>>2]=0;var na=Se[vi+4>>2],oa=1<>2]=la,Se[_a>>2]=qr,Se[_+(e+6)]=_a,Se[_+(e+3)]=qr,Se[_+(e+2)]=qr}else{if(31==(0|ra))var ba=0;else var ba=25-(ra>>>1)|0;for(var ba,ka=q<>2];;){var ua,ka;if((Se[ua+4>>2]&-8|0)==(0|q)){var ca=ua+8|0,ha=Me[ca>>2],da=Me[vi+16>>2],wa=ua>>>0>>0;do if(!wa){if(ha>>>0>>0)break;Se[ha+12>>2]=qr,Se[ca>>2]=qr,Se[_+(e+2)]=ha,Se[_+(e+3)]=ua,Se[_+(e+6)]=0;break a}while(0);throw Ka(),"Reached an unreachable!"}var pa=(ka>>>31<<2)+ua+16|0,Ea=Me[pa>>2];if(0==(0|Ea)){if(pa>>>0>=Me[vi+16>>2]>>>0){Se[pa>>2]=qr,Se[_+(e+6)]=ua,Se[_+(e+3)]=qr,Se[_+(e+2)]=qr;break a}throw Ka(),"Reached an unreachable!"}var ka=ka<<1,ua=Ea}}}while(0);var nr=$+8|0;break r}while(0);throw Ka(),"Reached an unreachable!"}var nr=0}while(0);var nr;return nr}function ia(r){var a;0==(0|Se[ti>>2])&&ba();var e=r>>>0<4294967232;r:do if(e){var i=Me[vi+24>>2];if(0==(0|i)){var v=0;break}var t=Me[vi+12>>2],f=t>>>0>(r+40|0)>>>0;do if(f){var _=Me[ti+8>>2],s=-40-r-1+t+_|0,n=Math.floor((s>>>0)/(_>>>0)),o=(n-1)*_|0,l=i,b=ua(l);if(0!=(8&Se[b+12>>2]|0))break;var k=re(0),a=(b+4|0)>>2;if((0|k)!=(Se[b>>2]+Se[a]|0))break;var u=o>>>0>2147483646?-2147483648-_|0:o,c=0|-u,h=re(c),d=re(0);if(!((0|h)!=-1&d>>>0>>0))break;var w=k-d|0;if((0|k)==(0|d))break;var p=Se[a]-w|0;Se[a]=p;var E=Se[vi+432>>2]-w|0;Se[vi+432>>2]=E;var A=Se[vi+24>>2],g=Se[vi+12>>2]-w|0;ca(A,g);var v=(0|k)!=(0|d);break r}while(0);if(Me[vi+12>>2]>>>0<=Me[vi+28>>2]>>>0){var v=0;break}Se[vi+28>>2]=-1;var v=0}else var v=0;while(0);var v;return 1&v}function va(r){var a,e,i,v,t,f,_,s=r>>2,n=0==(0|r);r:do if(!n){var o=r-8|0,l=o,b=Me[vi+16>>2],k=o>>>0>>0;a:do if(!k){var u=Me[r-4>>2],c=3&u;if(1==(0|c))break;var h=u&-8,f=h>>2,d=r+(h-8)|0,w=d,p=0==(1&u|0);e:do if(p){var E=Me[o>>2];if(0==(0|c))break r;var A=-8-E|0,t=A>>2,g=r+A|0,y=g,m=E+h|0;if(g>>>0>>0)break a;if((0|y)==(0|Se[vi+20>>2])){var v=(r+(h-4)|0)>>2;if(3!=(3&Se[v]|0)){var S=y,i=S>>2,M=m;break}Se[vi+8>>2]=m;var C=Se[v]&-2;Se[v]=C,Se[t+(s+1)]=1|m,Se[d>>2]=m;break r}if(E>>>0<256){var R=Me[t+(s+2)],T=Me[t+(s+3)];if((0|R)!=(0|T)){var O=((E>>>2&1073741822)<<2)+vi+40|0,N=(0|R)!=(0|O)&R>>>0>>0;do if(!N){if(!((0|T)==(0|O)|T>>>0>=b>>>0))break;Se[R+12>>2]=T,Se[T+8>>2]=R;var S=y,i=S>>2,M=m;break e}while(0);throw Ka(),"Reached an unreachable!"}var I=Se[vi>>2]&(1<<(E>>>3)^-1);Se[vi>>2]=I;var S=y,i=S>>2,M=m}else{var P=g,D=Me[t+(s+6)],L=Me[t+(s+3)],F=(0|L)==(0|P);do if(F){var X=A+(r+20)|0,j=Se[X>>2];if(0==(0|j)){var U=A+(r+16)|0,x=Se[U>>2];if(0==(0|x)){var z=0,e=z>>2;break}var V=U,B=x}else{var V=X,B=j;_=21}for(;;){var B,V,H=B+20|0,K=Se[H>>2];if(0==(0|K)){var Y=B+16|0,G=Me[Y>>2];if(0==(0|G))break;var V=Y,B=G}else var V=H,B=K}if(V>>>0>>0)throw Ka(),"Reached an unreachable!";Se[V>>2]=0;var z=B,e=z>>2}else{var W=Me[t+(s+2)];if(W>>>0>>0)throw Ka(),"Reached an unreachable!";Se[W+12>>2]=L,Se[L+8>>2]=W;var z=L,e=z>>2}while(0);var z;if(0==(0|D)){var S=y,i=S>>2,M=m;break}var Z=A+(r+28)|0,Q=(Se[Z>>2]<<2)+vi+304|0,q=(0|P)==(0|Se[Q>>2]);do{if(q){if(Se[Q>>2]=z,0!=(0|z))break;var $=Se[vi+4>>2]&(1<>2]^-1);Se[vi+4>>2]=$;var S=y,i=S>>2,M=m;break e}if(D>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";var J=D+16|0;if((0|Se[J>>2])==(0|P)?Se[J>>2]=z:Se[D+20>>2]=z,0==(0|z)){var S=y,i=S>>2,M=m;break e}}while(0);if(z>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";Se[e+6]=D;var rr=Me[t+(s+4)];if(0!=(0|rr)){if(rr>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";Se[e+4]=rr,Se[rr+24>>2]=z}var ar=Me[t+(s+5)];if(0==(0|ar)){var S=y,i=S>>2,M=m;break}if(ar>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";Se[e+5]=ar,Se[ar+24>>2]=z;var S=y,i=S>>2,M=m}}else var S=l,i=S>>2,M=h;while(0);var M,S,er=S;if(er>>>0>=d>>>0)break;var ir=r+(h-4)|0,vr=Me[ir>>2];if(0==(1&vr|0))break;var tr=0==(2&vr|0);do{if(tr){if((0|w)==(0|Se[vi+24>>2])){var fr=Se[vi+12>>2]+M|0;Se[vi+12>>2]=fr,Se[vi+24>>2]=S;var _r=1|fr;if(Se[i+1]=_r,(0|S)==(0|Se[vi+20>>2])&&(Se[vi+20>>2]=0,Se[vi+8>>2]=0),fr>>>0<=Me[vi+28>>2]>>>0)break r;ia(0);break r}if((0|w)==(0|Se[vi+20>>2])){var sr=Se[vi+8>>2]+M|0;Se[vi+8>>2]=sr,Se[vi+20>>2]=S;var nr=1|sr;Se[i+1]=nr;var or=er+sr|0;Se[or>>2]=sr;break r}var lr=(vr&-8)+M|0,br=vr>>>3,kr=vr>>>0<256;e:do if(kr){var ur=Me[s+f],cr=Me[((4|h)>>2)+s];if((0|ur)!=(0|cr)){var hr=((vr>>>2&1073741822)<<2)+vi+40|0,dr=(0|ur)==(0|hr);do{if(!dr){if(ur>>>0>2]>>>0){_=66;break}_=63;break}_=63}while(0);do if(63==_){if((0|cr)!=(0|hr)&&cr>>>0>2]>>>0)break;Se[ur+12>>2]=cr,Se[cr+8>>2]=ur;break e}while(0);throw Ka(),"Reached an unreachable!"}var wr=Se[vi>>2]&(1<>2]=wr}else{var pr=d,Er=Me[f+(s+4)],Ar=Me[((4|h)>>2)+s],gr=(0|Ar)==(0|pr);do if(gr){var yr=h+(r+12)|0,mr=Se[yr>>2];if(0==(0|mr)){var Sr=h+(r+8)|0,Mr=Se[Sr>>2];if(0==(0|Mr)){var Cr=0,a=Cr>>2;break}var Rr=Sr,Tr=Mr}else{var Rr=yr,Tr=mr;_=73}for(;;){var Tr,Rr,Or=Tr+20|0,Nr=Se[Or>>2];if(0==(0|Nr)){var Ir=Tr+16|0,Pr=Me[Ir>>2];if(0==(0|Pr))break;var Rr=Ir,Tr=Pr}else var Rr=Or,Tr=Nr}if(Rr>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";Se[Rr>>2]=0;var Cr=Tr,a=Cr>>2}else{var Dr=Me[s+f];if(Dr>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";Se[Dr+12>>2]=Ar, -Se[Ar+8>>2]=Dr;var Cr=Ar,a=Cr>>2}while(0);var Cr;if(0==(0|Er))break;var Lr=h+(r+20)|0,Fr=(Se[Lr>>2]<<2)+vi+304|0,Xr=(0|pr)==(0|Se[Fr>>2]);do{if(Xr){if(Se[Fr>>2]=Cr,0!=(0|Cr))break;var jr=Se[vi+4>>2]&(1<>2]^-1);Se[vi+4>>2]=jr;break e}if(Er>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";var Ur=Er+16|0;if((0|Se[Ur>>2])==(0|pr)?Se[Ur>>2]=Cr:Se[Er+20>>2]=Cr,0==(0|Cr))break e}while(0);if(Cr>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";Se[a+6]=Er;var xr=Me[f+(s+2)];if(0!=(0|xr)){if(xr>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";Se[a+4]=xr,Se[xr+24>>2]=Cr}var zr=Me[f+(s+3)];if(0==(0|zr))break;if(zr>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";Se[a+5]=zr,Se[zr+24>>2]=Cr}while(0);if(Se[i+1]=1|lr,Se[er+lr>>2]=lr,(0|S)!=(0|Se[vi+20>>2])){var Vr=lr;break}Se[vi+8>>2]=lr;break r}Se[ir>>2]=vr&-2,Se[i+1]=1|M,Se[er+M>>2]=M;var Vr=M}while(0);var Vr;if(Vr>>>0<256){var Br=Vr>>>2&1073741822,Hr=(Br<<2)+vi+40|0,Kr=Me[vi>>2],Yr=1<<(Vr>>>3),Gr=0==(Kr&Yr|0);do{if(!Gr){var Wr=(Br+2<<2)+vi+40|0,Zr=Me[Wr>>2];if(Zr>>>0>=Me[vi+16>>2]>>>0){var Qr=Zr,qr=Wr;break}throw Ka(),"Reached an unreachable!"}Se[vi>>2]=Kr|Yr;var Qr=Hr,qr=(Br+2<<2)+vi+40|0}while(0);var qr,Qr;Se[qr>>2]=S,Se[Qr+12>>2]=S,Se[i+2]=Qr,Se[i+3]=Hr;break r}var $r=S,Jr=Vr>>>8,ra=0==(0|Jr);do if(ra)var aa=0;else{if(Vr>>>0>16777215){var aa=31;break}var ea=(Jr+1048320|0)>>>16&8,va=Jr<>>16&4,_a=va<>>16&2,na=14-(fa|ea|sa)+(_a<>>15)|0,aa=Vr>>>((na+7|0)>>>0)&1|na<<1}while(0);var aa,oa=(aa<<2)+vi+304|0;Se[i+7]=aa,Se[i+5]=0,Se[i+4]=0;var la=Se[vi+4>>2],ba=1<>2]=ua,Se[oa>>2]=$r,Se[i+6]=oa,Se[i+3]=S,Se[i+2]=S}else{if(31==(0|aa))var ca=0;else var ca=25-(aa>>>1)|0;for(var ca,ha=Vr<>2];;){var da,ha;if((Se[da+4>>2]&-8|0)==(0|Vr)){var wa=da+8|0,pa=Me[wa>>2],Ea=Me[vi+16>>2],Aa=da>>>0>>0;do if(!Aa){if(pa>>>0>>0)break;Se[pa+12>>2]=$r,Se[wa>>2]=$r,Se[i+2]=pa,Se[i+3]=da,Se[i+6]=0;break e}while(0);throw Ka(),"Reached an unreachable!"}var ga=(ha>>>31<<2)+da+16|0,ya=Me[ga>>2];if(0==(0|ya)){if(ga>>>0>=Me[vi+16>>2]>>>0){Se[ga>>2]=$r,Se[i+6]=da,Se[i+3]=S,Se[i+2]=S;break e}throw Ka(),"Reached an unreachable!"}var ha=ha<<1,da=ya}}while(0);var ma=Se[vi+32>>2]-1|0;if(Se[vi+32>>2]=ma,0!=(0|ma))break r;ta();break r}while(0);throw Ka(),"Reached an unreachable!"}while(0)}function ta(){var r=Se[vi+452>>2],a=0==(0|r);r:do if(!a)for(var e=r;;){var e,i=Se[e+8>>2];if(0==(0|i))break r;var e=i}while(0);Se[vi+32>>2]=-1}function fa(r,a){if(0==(0|r))var e=Jr(a),i=e;else var v=la(r,a),i=v;var i;return i}function _a(r,a){var e,i=r>>>0<9;do if(i)var v=Jr(a),t=v;else{var f=r>>>0<16?16:r,_=0==(f-1&f|0);r:do if(_)var s=f;else{if(f>>>0<=16){var s=16;break}for(var n=16;;){var n,o=n<<1;if(o>>>0>=f>>>0){var s=o;break r}var n=o}}while(0);var s;if((-64-s|0)>>>0>a>>>0){if(a>>>0<11)var l=16;else var l=a+11&-8;var l,b=Jr(l+(s+12)|0);if(0==(0|b)){var t=0;break}var k=b-8|0;if(0==((b>>>0)%(s>>>0)|0))var u=k,c=0;else{var h=b+(s-1)&-s,d=h-8|0,w=k;if((d-w|0)>>>0>15)var p=d;else var p=h+(s-8)|0;var p,E=p-w|0,e=(b-4|0)>>2,A=Se[e],g=(A&-8)-E|0;if(0==(3&A|0)){var y=Se[k>>2]+E|0;Se[p>>2]=y,Se[p+4>>2]=g;var u=p,c=0}else{var m=p+4|0,S=g|1&Se[m>>2]|2;Se[m>>2]=S;var M=g+(p+4)|0,C=1|Se[M>>2];Se[M>>2]=C;var R=E|1&Se[e]|2;Se[e]=R;var T=b+(E-4)|0,O=1|Se[T>>2];Se[T>>2]=O;var u=p,c=b}}var c,u,N=u+4|0,I=Me[N>>2],P=0==(3&I|0);do if(P)var D=0;else{var L=I&-8;if(L>>>0<=(l+16|0)>>>0){var D=0;break}var F=L-l|0;Se[N>>2]=l|1&I|2,Se[u+(4|l)>>2]=3|F;var X=u+(4|L)|0,j=1|Se[X>>2];Se[X>>2]=j;var D=l+(u+8)|0}while(0);var D;0!=(0|c)&&va(c),0!=(0|D)&&va(D);var t=u+8|0}else{var U=Je();Se[U>>2]=12;var t=0}}while(0);var t;return t}function sa(r,a,e,i){var v,t;0==(0|Se[ti>>2])&&ba();var f=0==(0|i),_=0==(0|r);do{if(f){if(_){var s=Jr(0),n=s;t=30;break}var o=r<<2;if(o>>>0<11){var l=0,b=16;t=9;break}var l=0,b=o+11&-8;t=9;break}if(_){var n=i;t=30;break}var l=i,b=0;t=9;break}while(0);do if(9==t){var b,l,k=0==(1&e|0);r:do if(k){if(_){var u=0,c=0;break}for(var h=0,d=0;;){var d,h,w=Me[a+(d<<2)>>2];if(w>>>0<11)var p=16;else var p=w+11&-8;var p,E=p+h|0,A=d+1|0;if((0|A)==(0|r)){var u=0,c=E;break r}var h=E,d=A}}else{var g=Me[a>>2];if(g>>>0<11)var y=16;else var y=g+11&-8;var y,u=y,c=y*r|0}while(0);var c,u,m=Jr(b-4+c|0);if(0==(0|m)){var n=0;break}var S=m-8|0,M=Se[m-4>>2]&-8;if(0!=(2&e|0)){var C=-4-b+M|0;Fa(m,0,C,1)}if(0==(0|l)){var R=m+c|0,T=M-c|3;Se[m+(c-4)>>2]=T;var O=R,v=O>>2,N=c}else var O=l,v=O>>2,N=M;var N,O;Se[v]=m;var I=r-1|0,P=0==(0|I);r:do if(P)var D=S,L=N;else if(0==(0|u))for(var F=S,X=N,j=0;;){var j,X,F,U=Me[a+(j<<2)>>2];if(U>>>0<11)var x=16;else var x=U+11&-8;var x,z=X-x|0;Se[F+4>>2]=3|x;var V=F+x|0,B=j+1|0;if(Se[(B<<2>>2)+v]=x+(F+8)|0,(0|B)==(0|I)){var D=V,L=z;break r}var F=V,X=z,j=B}else for(var H=3|u,K=u+8|0,Y=S,G=N,W=0;;){var W,G,Y,Z=G-u|0;Se[Y+4>>2]=H;var Q=Y+u|0,q=W+1|0;if(Se[(q<<2>>2)+v]=Y+K|0,(0|q)==(0|I)){var D=Q,L=Z;break r}var Y=Q,G=Z,W=q}while(0);var L,D;Se[D+4>>2]=3|L;var n=O}while(0);var n;return n}function na(r){var a=r>>2;0==(0|Se[ti>>2])&&ba();var e=Me[vi+24>>2];if(0==(0|e))var i=0,v=0,t=0,f=0,_=0,s=0,n=0;else{for(var o=Me[vi+12>>2],l=o+40|0,b=vi+444|0,k=l,u=l,c=1;;){var c,u,k,b,h=Me[b>>2],d=h+8|0;if(0==(7&d|0))var w=0;else var w=7&-d;for(var w,p=b+4|0,E=h+w|0,A=c,g=u,y=k;;){var y,g,A,E;if(E>>>0>>0)break;if(E>>>0>=(h+Se[p>>2]|0)>>>0|(0|E)==(0|e))break;var m=Se[E+4>>2];if(7==(0|m))break;var S=m&-8,M=S+y|0;if(1==(3&m|0))var C=A+1|0,R=S+g|0;else var C=A,R=g;var R,C,E=E+S|0,A=C,g=R,y=M}var T=Me[b+8>>2];if(0==(0|T))break;var b=T,k=y,u=g,c=A}var O=Se[vi+432>>2],i=y,v=A,t=o,f=g,_=O-y|0,s=Se[vi+436>>2],n=O-g|0}var n,s,_,f,t,v,i;Se[a]=i,Se[a+1]=v,Se[a+2]=0,Se[a+3]=0,Se[a+4]=_,Se[a+5]=s,Se[a+6]=0,Se[a+7]=n,Se[a+8]=f,Se[a+9]=t}function oa(){0==(0|Se[ti>>2])&&ba();var r=Me[vi+24>>2],a=0==(0|r);r:do if(a)var e=0,i=0,v=0;else for(var t=Se[vi+436>>2],f=Me[vi+432>>2],_=vi+444|0,s=f-40-Se[vi+12>>2]|0;;){var s,_,n=Me[_>>2],o=n+8|0;if(0==(7&o|0))var l=0;else var l=7&-o;for(var l,b=_+4|0,k=n+l|0,u=s;;){var u,k;if(k>>>0>>0)break;if(k>>>0>=(n+Se[b>>2]|0)>>>0|(0|k)==(0|r))break;var c=Se[k+4>>2];if(7==(0|c))break;var h=c&-8,d=1==(3&c|0)?h:0,w=u-d|0,k=k+h|0,u=w}var p=Me[_+8>>2];if(0==(0|p)){var e=t,i=f,v=u;break r}var _=p,s=u}while(0);var v,i,e,E=Se[Se[qe>>2]+12>>2],A=(Qa(E,0|He.__str339,(ne=Oe,Oe+=4,Se[ne>>2]=e,ne)),Se[Se[qe>>2]+12>>2]),g=(Qa(A,0|He.__str1340,(ne=Oe,Oe+=4,Se[ne>>2]=i,ne)),Se[Se[qe>>2]+12>>2]);Qa(g,0|He.__str2341,(ne=Oe,Oe+=4,Se[ne>>2]=v,ne))}function la(r,a){var e,i,v,t=a>>>0>4294967231;r:do{if(!t){var f=r-8|0,_=f,i=(r-4|0)>>2,s=Me[i],n=s&-8,o=n-8|0,l=r+o|0,b=f>>>0>2]>>>0;do if(!b){var k=3&s;if(!(1!=(0|k)&(0|o)>-8))break;var e=(r+(n-4)|0)>>2;if(0==(1&Se[e]|0))break;if(a>>>0<11)var u=16;else var u=a+11&-8;var u,c=0==(0|k);do{if(c){var h=ka(_,u),d=0,w=h;v=17;break}if(n>>>0>>0){if((0|l)!=(0|Se[vi+24>>2])){v=21;break}var p=Se[vi+12>>2]+n|0;if(p>>>0<=u>>>0){v=21;break}var E=p-u|0,A=r+(u-8)|0;Se[i]=u|1&s|2;var g=1|E;Se[r+(u-4)>>2]=g,Se[vi+24>>2]=A,Se[vi+12>>2]=E;var d=0,w=_;v=17;break}var y=n-u|0;if(y>>>0<=15){var d=0,w=_;v=17;break}Se[i]=u|1&s|2,Se[r+(u-4)>>2]=3|y;var m=1|Se[e];Se[e]=m;var d=r+u|0,w=_;v=17;break}while(0);do if(17==v){var w,d;if(0==(0|w))break;0!=(0|d)&&va(d);var S=w+8|0;break r}while(0);var M=Jr(a);if(0==(0|M)){var S=0;break r}var C=0==(3&Se[i]|0)?8:4,R=n-C|0,T=R>>>0>>0?R:a;Pa(M,r,T,1),va(r);var S=M;break r}while(0);throw Ka(),"Reached an unreachable!"}var O=Je();Se[O>>2]=12;var S=0}while(0);var S;return S}function ba(){if(0==(0|Se[ti>>2])){var r=qa(8);if(0!=(r-1&r|0))throw Ka(),"Reached an unreachable!";Se[ti+8>>2]=r,Se[ti+4>>2]=r,Se[ti+12>>2]=-1,Se[ti+16>>2]=2097152,Se[ti+20>>2]=0,Se[vi+440>>2]=0;var a=$a(0);Se[ti>>2]=a&-16^1431655768}}function ka(r,a){var e=Se[r+4>>2]&-8,i=a>>>0<256;do if(i)var v=0;else{if(e>>>0>=(a+4|0)>>>0&&(e-a|0)>>>0<=Se[ti+8>>2]<<1>>>0){var v=r;break}var v=0}while(0);var v;return v}function ua(r){for(var a,e=vi+444|0,a=e>>2;;){var e,i=Me[a];if(i>>>0<=r>>>0&&(i+Se[a+1]|0)>>>0>r>>>0){var v=e;break}var t=Me[a+2];if(0==(0|t)){var v=0;break}var e=t,a=e>>2}var v;return v}function ca(r,a){var e=r,i=r+8|0;if(0==(7&i|0))var v=0;else var v=7&-i;var v,t=a-v|0;Se[vi+24>>2]=e+v|0,Se[vi+12>>2]=t,Se[v+(e+4)>>2]=1|t,Se[a+(e+4)>>2]=40;var f=Se[ti+16>>2];Se[vi+28>>2]=f}function ha(){for(var r=0;;){var r,a=r<<1,e=(a<<2)+vi+40|0;Se[vi+(a+3<<2)+40>>2]=e,Se[vi+(a+2<<2)+40>>2]=e;var i=r+1|0;if(32==(0|i))break;var r=i}}function da(r,a,e){var i,v,t,f,_=a>>2,s=r>>2,n=r+8|0;if(0==(7&n|0))var o=0;else var o=7&-n;var o,l=a+8|0;if(0==(7&l|0))var b=0,t=b>>2;else var b=7&-l,t=b>>2;var b,k=a+b|0,u=k,c=o+e|0,v=c>>2,h=r+c|0,d=h,w=k-(r+o)-e|0;Se[(o+4>>2)+s]=3|e;var p=(0|u)==(0|Se[vi+24>>2]);r:do if(p){var E=Se[vi+12>>2]+w|0;Se[vi+12>>2]=E,Se[vi+24>>2]=d;var A=1|E;Se[v+(s+1)]=A}else if((0|u)==(0|Se[vi+20>>2])){var g=Se[vi+8>>2]+w|0;Se[vi+8>>2]=g,Se[vi+20>>2]=d;var y=1|g;Se[v+(s+1)]=y;var m=r+g+c|0;Se[m>>2]=g}else{var S=Me[t+(_+1)];if(1==(3&S|0)){var M=S&-8,C=S>>>3,R=S>>>0<256;a:do if(R){var T=Me[((8|b)>>2)+_],O=Me[t+(_+3)];if((0|T)!=(0|O)){var N=((S>>>2&1073741822)<<2)+vi+40|0,I=(0|T)==(0|N);do{if(!I){if(T>>>0>2]>>>0){f=18;break}f=15;break}f=15}while(0);do if(15==f){if((0|O)!=(0|N)&&O>>>0>2]>>>0)break;Se[T+12>>2]=O,Se[O+8>>2]=T;break a}while(0);throw Ka(),"Reached an unreachable!"}var P=Se[vi>>2]&(1<>2]=P}else{var D=k,L=Me[((24|b)>>2)+_],F=Me[t+(_+3)],X=(0|F)==(0|D);do if(X){var j=16|b,U=j+(a+4)|0,x=Se[U>>2];if(0==(0|x)){var z=a+j|0,V=Se[z>>2];if(0==(0|V)){var B=0,i=B>>2;break}var H=z,K=V}else{var H=U,K=x;f=25}for(;;){var K,H,Y=K+20|0,G=Se[Y>>2];if(0==(0|G)){var W=K+16|0,Z=Me[W>>2];if(0==(0|Z))break;var H=W,K=Z}else var H=Y,K=G}if(H>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";Se[H>>2]=0;var B=K,i=B>>2}else{var Q=Me[((8|b)>>2)+_];if(Q>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";Se[Q+12>>2]=F,Se[F+8>>2]=Q;var B=F,i=B>>2}while(0);var B;if(0==(0|L))break;var q=b+(a+28)|0,$=(Se[q>>2]<<2)+vi+304|0,J=(0|D)==(0|Se[$>>2]);do{if(J){if(Se[$>>2]=B,0!=(0|B))break;var rr=Se[vi+4>>2]&(1<>2]^-1);Se[vi+4>>2]=rr;break a}if(L>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";var ar=L+16|0;if((0|Se[ar>>2])==(0|D)?Se[ar>>2]=B:Se[L+20>>2]=B,0==(0|B))break a}while(0);if(B>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";Se[i+6]=L;var er=16|b,ir=Me[(er>>2)+_];if(0!=(0|ir)){if(ir>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";Se[i+4]=ir,Se[ir+24>>2]=B}var vr=Me[(er+4>>2)+_];if(0==(0|vr))break;if(vr>>>0>2]>>>0)throw Ka(),"Reached an unreachable!";Se[i+5]=vr,Se[vr+24>>2]=B}while(0);var tr=a+(M|b)|0,fr=M+w|0}else var tr=u,fr=w;var fr,tr,_r=tr+4|0,sr=Se[_r>>2]&-2;if(Se[_r>>2]=sr,Se[v+(s+1)]=1|fr,Se[(fr>>2)+s+v]=fr,fr>>>0<256){var nr=fr>>>2&1073741822,or=(nr<<2)+vi+40|0,lr=Me[vi>>2],br=1<<(fr>>>3),kr=0==(lr&br|0);do{if(!kr){var ur=(nr+2<<2)+vi+40|0,cr=Me[ur>>2];if(cr>>>0>=Me[vi+16>>2]>>>0){var hr=cr,dr=ur;break}throw Ka(),"Reached an unreachable!"}Se[vi>>2]=lr|br;var hr=or,dr=(nr+2<<2)+vi+40|0}while(0);var dr,hr;Se[dr>>2]=d,Se[hr+12>>2]=d,Se[v+(s+2)]=hr,Se[v+(s+3)]=or}else{var wr=h,pr=fr>>>8,Er=0==(0|pr);do if(Er)var Ar=0;else{if(fr>>>0>16777215){var Ar=31;break}var gr=(pr+1048320|0)>>>16&8,yr=pr<>>16&4,Sr=yr<>>16&2,Cr=14-(mr|gr|Mr)+(Sr<>>15)|0,Ar=fr>>>((Cr+7|0)>>>0)&1|Cr<<1}while(0);var Ar,Rr=(Ar<<2)+vi+304|0;Se[v+(s+7)]=Ar;var Tr=c+(r+16)|0;Se[v+(s+5)]=0,Se[Tr>>2]=0;var Or=Se[vi+4>>2],Nr=1<>2]=Ir,Se[Rr>>2]=wr,Se[v+(s+6)]=Rr,Se[v+(s+3)]=wr,Se[v+(s+2)]=wr}else{if(31==(0|Ar))var Pr=0;else var Pr=25-(Ar>>>1)|0;for(var Pr,Dr=fr<>2];;){var Lr,Dr;if((Se[Lr+4>>2]&-8|0)==(0|fr)){var Fr=Lr+8|0,Xr=Me[Fr>>2],jr=Me[vi+16>>2],Ur=Lr>>>0>>0;do if(!Ur){if(Xr>>>0>>0)break;Se[Xr+12>>2]=wr,Se[Fr>>2]=wr,Se[v+(s+2)]=Xr,Se[v+(s+3)]=Lr,Se[v+(s+6)]=0;break r}while(0);throw Ka(),"Reached an unreachable!"}var xr=(Dr>>>31<<2)+Lr+16|0,zr=Me[xr>>2];if(0==(0|zr)){if(xr>>>0>=Me[vi+16>>2]>>>0){Se[xr>>2]=wr,Se[v+(s+6)]=Lr,Se[v+(s+3)]=wr,Se[v+(s+2)]=wr;break r}throw Ka(),"Reached an unreachable!"}var Dr=Dr<<1,Lr=zr}}}}while(0);return r+(8|o)|0}function wa(r){return 0|He.__str3342}function pa(r){return 0|He.__str14343}function Ea(r){Se[r>>2]=si+8|0}function Aa(r){0!=(0|r)&&va(r)}function ga(r){ya(r);var a=r;Aa(a)}function ya(r){var a=0|r;Ye(a)}function ma(r){var a=0|r;Ea(a),Se[r>>2]=ni+8|0}function Sa(r){var a=0|r;ya(a);var e=r;Aa(e)}function Ma(r,a){var e,i,v=Me[vi+24>>2],i=v>>2,t=v,f=ua(t),_=Se[f>>2],s=Se[f+4>>2],n=_+s|0,o=_+(s-39)|0;if(0==(7&o|0))var l=0;else var l=7&-o;var l,b=_+(s-47)+l|0,k=b>>>0<(v+16|0)>>>0?t:b,u=k+8|0,e=u>>2,c=u,h=r,d=a-40|0;ca(h,d);var w=k+4|0;Se[w>>2]=27,Se[e]=Se[vi+444>>2],Se[e+1]=Se[vi+448>>2],Se[e+2]=Se[vi+452>>2],Se[e+3]=Se[vi+456>>2],Se[vi+444>>2]=r,Se[vi+448>>2]=a,Se[vi+456>>2]=0,Se[vi+452>>2]=c;var p=k+28|0;Se[p>>2]=7;var E=(k+32|0)>>>0>>0;r:do if(E)for(var A=p;;){var A,g=A+4|0;if(Se[g>>2]=7,(A+8|0)>>>0>=n>>>0)break r;var A=g}while(0);var y=(0|k)==(0|t);r:do if(!y){var m=k-v|0,S=t+m|0,M=m+(t+4)|0,C=Se[M>>2]&-2;Se[M>>2]=C;var R=1|m;Se[i+1]=R;var T=S;if(Se[T>>2]=m,m>>>0<256){var O=m>>>2&1073741822,N=(O<<2)+vi+40|0,I=Me[vi>>2],P=1<<(m>>>3),D=0==(I&P|0);do{if(!D){var L=(O+2<<2)+vi+40|0,F=Me[L>>2];if(F>>>0>=Me[vi+16>>2]>>>0){var X=F,j=L;break}throw Ka(),"Reached an unreachable!"}var U=I|P;Se[vi>>2]=U;var X=N,j=(O+2<<2)+vi+40|0}while(0);var j,X;Se[j>>2]=v,Se[X+12>>2]=v,Se[i+2]=X,Se[i+3]=N}else{var x=v,z=m>>>8,V=0==(0|z);do if(V)var B=0;else{if(m>>>0>16777215){var B=31;break}var H=(z+1048320|0)>>>16&8,K=z<>>16&4,G=K<>>16&2,Z=14-(Y|H|W)+(G<>>15)|0,B=m>>>((Z+7|0)>>>0)&1|Z<<1}while(0);var B,Q=(B<<2)+vi+304|0;Se[i+7]=B,Se[i+5]=0,Se[i+4]=0;var q=Se[vi+4>>2],$=1<>2]=J,Se[Q>>2]=x,Se[i+6]=Q,Se[i+3]=v,Se[i+2]=v}else{if(31==(0|B))var rr=0;else var rr=25-(B>>>1)|0;for(var rr,ar=m<>2];;){var er,ar;if((Se[er+4>>2]&-8|0)==(0|m)){var ir=er+8|0,vr=Me[ir>>2],tr=Me[vi+16>>2],fr=er>>>0>>0;do if(!fr){if(vr>>>0>>0)break;Se[vr+12>>2]=x,Se[ir>>2]=x,Se[i+2]=vr,Se[i+3]=er,Se[i+6]=0;break r}while(0);throw Ka(),"Reached an unreachable!"}var _r=(ar>>>31<<2)+er+16|0,sr=Me[_r>>2];if(0==(0|sr)){if(_r>>>0>=Me[vi+16>>2]>>>0){Se[_r>>2]=x,Se[i+6]=er,Se[i+3]=v,Se[i+2]=v;break r}throw Ka(),"Reached an unreachable!"}var ar=ar<<1,er=sr}}}}while(0)}function Ca(r){return d(r)}function Ra(r,a){var e=0;do Ae[r+e]=Ae[a+e],e++;while(0!=Ae[a+e-1]);return r}function Ta(){var r=Ta;return r.LLVM_SAVEDSTACKS||(r.LLVM_SAVEDSTACKS=[]),r.LLVM_SAVEDSTACKS.push(le.stackSave()),r.LLVM_SAVEDSTACKS.length-1}function Oa(r){var a=Ta,e=a.LLVM_SAVEDSTACKS[r];a.LLVM_SAVEDSTACKS.splice(r,1),le.stackRestore(e)}function Na(r,a,e){for(var i=0;it?1:-1;i++}return 0}function Ia(r,a){var e=Ca(r),i=0;do Ae[r+e+i]=Ae[a+i],i++;while(0!=Ae[a+i-1]);return r}function Pa(r,a,e,i){if(e>=20&&a%2==r%2)if(a%4==r%4){for(var v=a+e;a%4;)Ae[r++]=Ae[a++];for(var t=a>>2,f=r>>2,_=v>>2;t<_;)Se[f++]=Se[t++];for(a=t<<2,r=f<<2;a>1,n=r>>1,o=v>>1;st?1:-1}return 0}function Fa(r,a,e,i){if(e>=20){for(var v=r+e;r%4;)Ae[r++]=a;a<0&&(a+=256);for(var t=r>>2,f=v>>2,_=a|a<<8|a<<16|a<<24;t>2],xe[1]=Se[a+_+4>>2],e=ze[0]):"i64"==r?e=[Se[a+_>>2],Se[a+_+4>>2]]:(r="i32",e=Se[a+_>>2]),_+=le.getNativeFieldSize(r),e}for(var i,v,t,f=r,_=0,s=[];;){var n=f;if(i=Ae[f],0===i)break;if(v=Ae[f+1],i=="%".charCodeAt(0)){var o=!1,l=!1,b=!1,k=!1;r:for(;;){switch(v){case"+".charCodeAt(0):o=!0;break;case"-".charCodeAt(0):l=!0;break;case"#".charCodeAt(0):b=!0;break;case"0".charCodeAt(0):if(k)break r;k=!0;break;default:break r}f++,v=Ae[f+1]}var u=0;if(v=="*".charCodeAt(0))u=e("i32"),f++,v=Ae[f+1];else for(;v>="0".charCodeAt(0)&&v<="9".charCodeAt(0);)u=10*u+(v-"0".charCodeAt(0)),f++,v=Ae[f+1];var c=!1;if(v==".".charCodeAt(0)){var h=0;if(c=!0,f++,v=Ae[f+1],v=="*".charCodeAt(0))h=e("i32"),f++;else for(;;){var d=Ae[f+1];if(d<"0".charCodeAt(0)||d>"9".charCodeAt(0))break;h=10*h+(d-"0".charCodeAt(0)),f++}v=Ae[f+1]}else var h=6;var E;switch(String.fromCharCode(v)){case"h":var A=Ae[f+2];A=="h".charCodeAt(0)?(f++,E=1):E=2;break;case"l":var A=Ae[f+2];A=="l".charCodeAt(0)?(f++,E=8):E=4;break;case"L":case"q":case"j":E=8;break;case"z":case"t":case"I":E=4;break;default:E=null}if(E&&f++,v=Ae[f+1],["d","i","u","o","x","X","p"].indexOf(String.fromCharCode(v))!=-1){var m=v=="d".charCodeAt(0)||v=="i".charCodeAt(0);E=E||4;var t=e("i"+8*E);if(8==E&&(t=le.makeBigInt(t[0],t[1],v=="u".charCodeAt(0))),E<=4){var S=Math.pow(256,E)-1;t=(m?y:g)(t&S,8*E)}var M,C=Math.abs(t),R="";if(v=="d".charCodeAt(0)||v=="i".charCodeAt(0))M=y(t,8*E,1).toString(10);else if(v=="u".charCodeAt(0))M=g(t,8*E,1).toString(10),t=Math.abs(t);else if(v=="o".charCodeAt(0))M=(b?"0":"")+C.toString(8);else if(v=="x".charCodeAt(0)||v=="X".charCodeAt(0)){if(R=b?"0x":"",t<0){t=-t,M=(C-1).toString(16);for(var T=[],O=0;OP&&P>=-4?(v=(v=="g".charCodeAt(0)?"f":"F").charCodeAt(0),h-=P+1):(v=(v=="g".charCodeAt(0)?"e":"E").charCodeAt(0),h--),I=Math.min(h,20)}v=="e".charCodeAt(0)||v=="E".charCodeAt(0)?(M=t.toExponential(I),/[eE][-+]\\d$/.test(M)&&(M=M.slice(0,-1)+"0"+M.slice(-1))):v!="f".charCodeAt(0)&&v!="F".charCodeAt(0)||(M=t.toFixed(I));var D=M.split("e");if(N&&!b)for(;D[0].length>1&&D[0].indexOf(".")!=-1&&("0"==D[0].slice(-1)||"."==D[0].slice(-1));)D[0]=D[0].slice(0,-1);else for(b&&M.indexOf(".")==-1&&(D[0]+=".");h>I++;)D[0]+="0";M=D[0]+(D.length>1?"e"+D[1]:""),v=="E".charCodeAt(0)&&(M=M.toUpperCase()),o&&t>=0&&(M="+"+M)}else M=(t<0?"-":"")+"inf",k=!1;for(;M.lengthh&&(L=L.slice(0,h))):L=p("(null)",!0),!l)for(;L.length0;)s.push(" ".charCodeAt(0));l||s.push(e("i8"))}else if(v=="n".charCodeAt(0)){var X=e("i32*");Se[X>>2]=s.length}else if(v=="%".charCodeAt(0))s.push(i);else for(var O=n;O="0".charCodeAt(0)&&r<="9".charCodeAt(0)}function Ha(r){for(var a;(a=Ae[r])&&Va(a);)r++;if(!a||!Ba(a))return 0;for(var e=r;(a=Ae[e])&&Ba(a);)e++;return Math.floor(Number(s(r).substr(0,e-r)))}function Ka(r){throw ke=!0,"ABORT: "+r+", at "+(new Error).stack}function Ya(r){return Ya.ret||(Ya.ret=_([0],"i32",we)),Se[Ya.ret>>2]=r,r}function Ga(r,a,e,i){var v=$e.streams[r];if(!v||v.object.isDevice)return Ya(Ge.EBADF),-1;if(v.isWrite){if(v.object.isFolder)return Ya(Ge.EISDIR),-1;if(e<0||i<0)return Ya(Ge.EINVAL),-1;for(var t=v.object.contents;t.length>2]=a),a}function Ja(){return Ya.ret}function re(r){var a=re;a.called||(Ie=o(Ie),a.called=!0);var e=Ie;return 0!=r&&le.staticAlloc(r),e}function ae(){return Se[ae.buf>>2]}function ee(r){r=r||Module.arguments,k();var a=null;return Module._main&&(a=Module.callMain(r),Module.noExitRuntime||u()),a}var ie=[],ve=false,te="object"==typeof window,fe="function"==typeof importScripts,_e=!te&&!ve&&!fe;if(ve){print=function(r){process.stdout.write(r+"\\n")},printErr=function(r){process.stderr.write(r+"\\n")};var se=require("fs");read=function(r){var a=se.readFileSync(r).toString();return a||"/"==r[0]||(r=__dirname.split("/").slice(0,-1).join("/")+"/src/"+r,a=se.readFileSync(r).toString()),a},load=function(a){r(read(a))},ie=process.argv.slice(2)}else if(_e)this.read||(this.read=function(r){snarf(r)}),"undefined"!=typeof scriptArgs?ie=scriptArgs:"undefined"!=typeof arguments&&(ie=arguments);else if(te)this.print=printErr=function(r){console.log(r)},this.read=function(r){var a=new XMLHttpRequest;return a.open("GET",r,!1),a.send(null),a.responseText},this.arguments&&(ie=arguments);else{if(!fe)throw"Unknown runtime environment. Where are we?";this.load=importScripts}"undefined"==typeof load&&"undefined"!=typeof read&&(this.load=function(a){r(read(a))}),"undefined"==typeof printErr&&(this.printErr=function(){}),"undefined"==typeof print&&(this.print=printErr);try{this.Module=Module}catch(r){this.Module=Module={}}Module.arguments||(Module.arguments=ie),Module.print&&(print=Module.print);var ne,oe,le={stackSave:function(){return Oe},stackRestore:function(r){Oe=r},forceAlign:function(r,a){if(a=a||4,1==a)return r;if(isNumber(r)&&isNumber(a))return Math.ceil(r/a)*a;if(isNumber(a)&&isPowerOfTwo(a)){var e=log2(a);return"(((("+r+")+"+(a-1)+")>>"+e+")<<"+e+")"}return"Math.ceil(("+r+")/"+a+")*"+a},isNumberType:function(r){return r in le.INT_TYPES||r in le.FLOAT_TYPES},isPointerType:function(r){return"*"==r[r.length-1]},isStructType:function(r){return!isPointerType(r)&&(!!/^\\[\\d+\\ x\\ (.*)\\]/.test(r)||(!!/?/.test(r)||"%"==r[0]))},INT_TYPES:{i1:0,i8:0,i16:0,i32:0,i64:0},FLOAT_TYPES:{float:0,double:0},bitshift64:function(r,e,i,v){var t=Math.pow(2,v)-1;if(v<32)switch(i){case"shl":return[r<>>32-v];case"ashr":return[(r>>>v|(e&t)<<32-v)>>0>>>0,e>>v>>>0];case"lshr":return[(r>>>v|(e&t)<<32-v)>>>0,e>>>v]}else if(32==v)switch(i){case"shl":return[0,r];case"ashr":return[e,(0|e)<0?t:0];case"lshr":return[e,0]}else switch(i){case"shl":return[0,r<>v-32>>>0,(0|e)<0?t:0];case"lshr":return[e>>>v-32,0]}a("unknown bitshift64 op: "+[value,i,v])},or64:function(r,a){var e=0|r|(0|a),i=4294967296*(Math.round(r/4294967296)|Math.round(a/4294967296));return e+i},and64:function(r,a){var e=(0|r)&(0|a),i=4294967296*(Math.round(r/4294967296)&Math.round(a/4294967296));return e+i},xor64:function(r,a){var e=(0|r)^(0|a),i=4294967296*(Math.round(r/4294967296)^Math.round(a/4294967296));return e+i},getNativeTypeSize:function(r,a){if(1==le.QUANTUM_SIZE)return 1;var i={"%i1":1,"%i8":1,"%i16":2,"%i32":4,"%i64":8,"%float":4,"%double":8}["%"+r];if(!i)if("*"==r[r.length-1])i=le.QUANTUM_SIZE;else if("i"==r[0]){var v=parseInt(r.substr(1));e(v%8==0),i=v/8}return i},getNativeFieldSize:function(r){return Math.max(le.getNativeTypeSize(r),le.QUANTUM_SIZE)},dedup:function(r,a){var e={};return a?r.filter(function(r){return!e[r[a]]&&(e[r[a]]=!0,!0)}):r.filter(function(r){return!e[r]&&(e[r]=!0,!0)})},set:function(){for(var r="object"==typeof arguments[0]?arguments[0]:arguments,a={},e=0;e=0&&a.push(f-e),e=f,f}),r.flatSize=le.alignMemory(r.flatSize,r.alignSize),0==a.length?r.flatFactor=r.flatSize:1==le.dedup(a).length&&(r.flatFactor=a[0]),r.needsFlattening=1!=r.flatFactor,r.flatIndexes},generateStructInfo:function(r,a,i){var v,t;if(a){if(i=i||0,v=("undefined"==typeof Types?le.typeInfo:Types.types)[a],!v)return null;e(v.fields.length===r.length,"Number of named fields must match the type for "+a),t=v.flatIndexes}else{var v={fields:r.map(function(r){return r[0]})};t=le.calculateStructAlignment(v)}var f={__size__:v.flatSize};return a?r.forEach(function(r,a){if("string"==typeof r)f[r]=t[a]+i;else{var e;for(var _ in r)e=_;f[e]=le.generateStructInfo(r[e],v.fields[a],t[a])}}):r.forEach(function(r,a){f[r[1]]=t[a]}),f},stackAlloc:function(r){var a=Oe;return Oe+=r,Oe=Oe+3>>2<<2,a},staticAlloc:function(r){var a=Ie;return Ie+=r,Ie=Ie+3>>2<<2,Ie>=Le&&l(),a},alignMemory:function(r,a){var e=r=Math.ceil(r/(a?a:4))*(a?a:4);return e},makeBigInt:function(r,a,e){var i=e?(r>>>0)+4294967296*(a>>>0):(r>>>0)+4294967296*(0|a);return i},QUANTUM_SIZE:4,__dummy__:0},be={MAX_ALLOWED:0,corrections:0,sigs:{},note:function(r,e,i){e||(this.corrections++,this.corrections>=this.MAX_ALLOWED&&a("\\n\\nToo many corrections!"))},print:function(){}},ke=!1,ue=0,ce=this;Module.ccall=i,Module.setValue=t,Module.getValue=f;var he=0,de=1,we=2;Module.ALLOC_NORMAL=he,Module.ALLOC_STACK=de,Module.ALLOC_STATIC=we,Module.allocate=_,Module.Pointer_stringify=s,Module.Array_stringify=n;var pe,Ee,Ae,ge,ye,me,Se,Me,Ce,Re,Te,Oe,Ne,Ie,Pe=4096,De=Module.TOTAL_STACK||5242880,Le=Module.TOTAL_MEMORY||10485760;Module.FAST_MEMORY||2097152;e(!!(Int32Array&&Float64Array&&new Int32Array(1).subarray&&new Int32Array(1).set),"Cannot fallback to non-typed array case: Code is too specialized");var Fe=new ArrayBuffer(Le);Ae=new Int8Array(Fe),ye=new Int16Array(Fe),Se=new Int32Array(Fe),ge=new Uint8Array(Fe),me=new Uint16Array(Fe),Me=new Uint32Array(Fe),Ce=new Float32Array(Fe),Re=new Float64Array(Fe),Se[0]=255,e(255===ge[0]&&0===ge[3],"Typed arrays 2 must be run on a little-endian system");var Xe=p("(null)");Ie=Xe.length;for(var je=0;je>2)),ze=(Ce.subarray(Ue>>2),Re.subarray(Ue>>3));Ne=Ue+8,Ie=o(Ne);var Ve=[],Be=[];Module.Array_copy=c,Module.TypedArray_copy=h,Module.String_len=d,Module.String_copy=w,Module.intArrayFromString=p,Module.intArrayToString=E,Module.writeStringToMemory=A;var He=[],Ke=0;O.X=1,N.X=1,V.X=1,H.X=1,G.X=1,W.X=1,q.X=1,$.X=1,rr.X=1,ar.X=1,er.X=1,vr.X=1,nr.X=1,or.X=1,kr.X=1,hr.X=1,Ar.X=1,Sr.X=1,Tr.X=1,Ir.X=1,Pr.X=1,Dr.X=1,Lr.X=1,Fr.X=1,Xr.X=1,zr.X=1,Vr.X=1,Br.X=1,Gr.X=1,$r.X=1,Module._malloc=Jr,Jr.X=1,ra.X=1,aa.X=1,ea.X=1,ia.X=1,Module._free=va,va.X=1,_a.X=1,sa.X=1,na.X=1,oa.X=1,la.X=1,da.X=1,Ma.X=1;var Ye,Ge={E2BIG:7,EACCES:13,EADDRINUSE:98,EADDRNOTAVAIL:99,EAFNOSUPPORT:97,EAGAIN:11,EALREADY:114,EBADF:9,EBADMSG:74,EBUSY:16,ECANCELED:125,ECHILD:10,ECONNABORTED:103,ECONNREFUSED:111,ECONNRESET:104,EDEADLK:35,EDESTADDRREQ:89,EDOM:33,EDQUOT:122,EEXIST:17,EFAULT:14,EFBIG:27,EHOSTUNREACH:113,EIDRM:43,EILSEQ:84,EINPROGRESS:115,EINTR:4,EINVAL:22,EIO:5,EISCONN:106,EISDIR:21,ELOOP:40,EMFILE:24,EMLINK:31,EMSGSIZE:90,EMULTIHOP:72,ENAMETOOLONG:36,ENETDOWN:100,ENETRESET:102,ENETUNREACH:101,ENFILE:23,ENOBUFS:105,ENODATA:61,ENODEV:19,ENOENT:2,ENOEXEC:8,ENOLCK:37,ENOLINK:67,ENOMEM:12,ENOMSG:42,ENOPROTOOPT:92,ENOSPC:28,ENOSR:63,ENOSTR:60,ENOSYS:38,ENOTCONN:107,ENOTDIR:20,ENOTEMPTY:39,ENOTRECOVERABLE:131,ENOTSOCK:88,ENOTSUP:95,ENOTTY:25,ENXIO:6,EOVERFLOW:75,EOWNERDEAD:130,EPERM:1,EPIPE:32,EPROTO:71,EPROTONOSUPPORT:93,EPROTOTYPE:91,ERANGE:34,EROFS:30,ESPIPE:29,ESRCH:3,ESTALE:116,ETIME:62,ETIMEDOUT:110,ETXTBSY:26,EWOULDBLOCK:11,EXDEV:18},We=0,Ze=0,Qe=0,qe=0,$e={currentPath:"/",nextInode:2,streams:[null],ignorePermissions:!0,absolutePath:function(r,a){if("string"!=typeof r)return null;void 0===a&&(a=$e.currentPath),r&&"/"==r[0]&&(a="");for(var e=a+"/"+r,i=e.split("/").reverse(),v=[""];i.length;){var t=i.pop();""==t||"."==t||(".."==t?v.length>1&&v.pop():v.push(t))}return 1==v.length?"/":v.join("/")},analyzePath:function(r,a,e){var i={isRoot:!1,exists:!1,error:0,name:null,path:null,object:null,parentExists:!1,parentPath:null,parentObject:null};if(r=$e.absolutePath(r),"/"==r)i.isRoot=!0,i.exists=i.parentExists=!0,i.name="/",i.path=i.parentPath="/",i.object=i.parentObject=$e.root;else if(null!==r){e=e||0,r=r.slice(1).split("/");for(var v=$e.root,t=[""];r.length;){1==r.length&&v.isFolder&&(i.parentExists=!0,i.parentPath=1==t.length?"/":t.join("/"),i.parentObject=v,i.name=r[0]);var f=r.shift();if(!v.isFolder){i.error=Ge.ENOTDIR;break}if(!v.read){i.error=Ge.EACCES;break}if(!v.contents.hasOwnProperty(f)){i.error=Ge.ENOENT;break}if(v=v.contents[f],v.link&&(!a||0!=r.length)){if(e>40){i.error=Ge.ELOOP;break}var _=$e.absolutePath(v.link,t.join("/"));return $e.analyzePath([_].concat(r).join("/"),a,e+1)}t.push(f),0==r.length&&(i.exists=!0,i.path=t.join("/"),i.object=v)}return i}return i},findObject:function(r,a){$e.ensureRoot();var e=$e.analyzePath(r,a);return e.exists?e.object:(Ya(e.error),null)},createObject:function(r,a,e,i,v){if(r||(r="/"),"string"==typeof r&&(r=$e.findObject(r)),!r)throw Ya(Ge.EACCES),new Error("Parent path must exist.");if(!r.isFolder)throw Ya(Ge.ENOTDIR), -new Error("Parent must be a folder.");if(!r.write&&!$e.ignorePermissions)throw Ya(Ge.EACCES),new Error("Parent folder must be writeable.");if(!a||"."==a||".."==a)throw Ya(Ge.ENOENT),new Error("Name must not be empty.");if(r.contents.hasOwnProperty(a))throw Ya(Ge.EEXIST),new Error("Can't overwrite object.");r.contents[a]={read:void 0===i||i,write:void 0!==v&&v,timestamp:Date.now(),inodeNumber:$e.nextInode++};for(var t in e)e.hasOwnProperty(t)&&(r.contents[a][t]=e[t]);return r.contents[a]},createFolder:function(r,a,e,i){var v={isFolder:!0,isDevice:!1,contents:{}};return $e.createObject(r,a,v,e,i)},createPath:function(r,a,e,i){var v=$e.findObject(r);if(null===v)throw new Error("Invalid parent.");for(a=a.split("/").reverse();a.length;){var t=a.pop();t&&(v.contents.hasOwnProperty(t)||$e.createFolder(v,t,e,i),v=v.contents[t])}return v},createFile:function(r,a,e,i,v){return e.isFolder=!1,$e.createObject(r,a,e,i,v)},createDataFile:function(r,a,e,i,v){if("string"==typeof e){for(var t=new Array(e.length),f=0,_=e.length;f<_;++f)t[f]=e.charCodeAt(f);e=t}var s={isDevice:!1,contents:e};return $e.createFile(r,a,s,i,v)},createLazyFile:function(r,a,e,i,v){var t={isDevice:!1,url:e};return $e.createFile(r,a,t,i,v)},createLink:function(r,a,e,i,v){var t={isDevice:!1,link:e};return $e.createFile(r,a,t,i,v)},createDevice:function(r,a,e,i){if(!e&&!i)throw new Error("A device must have at least one callback defined.");var v={isDevice:!0,input:e,output:i};return $e.createFile(r,a,v,Boolean(e),Boolean(i))},forceLoadFile:function(r){if(r.isDevice||r.isFolder||r.link||r.contents)return!0;var a=!0;if("undefined"!=typeof XMLHttpRequest)e("Cannot do synchronous binary XHRs in modern browsers. Use --embed-file or --preload-file in emcc");else{if("undefined"==typeof read)throw new Error("Cannot load without read() or XMLHttpRequest.");try{r.contents=p(read(r.url),!0)}catch(r){a=!1}}return a||Ya(Ge.EIO),a},ensureRoot:function(){$e.root||($e.root={read:!0,write:!0,isFolder:!0,isDevice:!1,timestamp:Date.now(),inodeNumber:1,contents:{}})},init:function(r,a,i){function v(r){null===r||r==="\\n".charCodeAt(0)?(a.printer(a.buffer.join("")),a.buffer=[]):a.buffer.push(String.fromCharCode(r))}e(!$e.init.initialized,"FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)"),$e.init.initialized=!0,$e.ensureRoot(),r=r||Module.stdin,a=a||Module.stdout,i=i||Module.stderr;var t=!0,f=!0,s=!0;r||(t=!1,r=function(){if(!r.cache||!r.cache.length){var a;"undefined"!=typeof window&&"function"==typeof window.prompt?a=window.prompt("Input: "):"function"==typeof readline&&(a=readline()),a||(a=""),r.cache=p(a+"\\n",!0)}return r.cache.shift()}),a||(f=!1,a=v),a.printer||(a.printer=print),a.buffer||(a.buffer=[]),i||(s=!1,i=v),i.printer||(i.printer=print),i.buffer||(i.buffer=[]),$e.createFolder("/","tmp",!0,!0);var n=$e.createFolder("/","dev",!0,!0),o=$e.createDevice(n,"stdin",r),l=$e.createDevice(n,"stdout",null,a),b=$e.createDevice(n,"stderr",null,i);$e.createDevice(n,"tty",r,a),$e.streams[1]={path:"/dev/stdin",object:o,position:0,isRead:!0,isWrite:!1,isAppend:!1,isTerminal:!t,error:!1,eof:!1,ungotten:[]},$e.streams[2]={path:"/dev/stdout",object:l,position:0,isRead:!1,isWrite:!0,isAppend:!1,isTerminal:!f,error:!1,eof:!1,ungotten:[]},$e.streams[3]={path:"/dev/stderr",object:b,position:0,isRead:!1,isWrite:!0,isAppend:!1,isTerminal:!s,error:!1,eof:!1,ungotten:[]},We=_([1],"void*",we),Ze=_([2],"void*",we),Qe=_([3],"void*",we),$e.createPath("/","dev/shm/tmp",!0,!0),$e.streams[We]=$e.streams[1],$e.streams[Ze]=$e.streams[2],$e.streams[Qe]=$e.streams[3],qe=_([_([0,0,0,0,We,0,0,0,Ze,0,0,0,Qe,0,0,0],"void*",we)],"void*",we)},quit:function(){$e.init.initialized&&($e.streams[2]&&$e.streams[2].object.output.buffer.length>0&&$e.streams[2].object.output("\\n".charCodeAt(0)),$e.streams[3]&&$e.streams[3].object.output.buffer.length>0&&$e.streams[3].object.output("\\n".charCodeAt(0)))}},Je=Ja;Ve.unshift({func:function(){$e.ignorePermissions=!1,$e.init.initialized||$e.init()}}),Be.push({func:function(){$e.quit()}}),Ya(0),ae.buf=_(12,"void*",we),Module.callMain=function(r){function a(){for(var r=0;r<3;r++)i.push(0)}var e=r.length+1,i=[_(p("/bin/this.program"),"i8",we)];a();for(var v=0;v>2]=0|He.__str,Se[ri+4>>2]=0|He.__str1,Se[ri+16>>2]=0|He.__str2,Se[ri+20>>2]=0|He.__str3,Se[ri+32>>2]=0|He.__str4,Se[ri+36>>2]=0|He.__str5,Se[ri+48>>2]=0|He.__str6,Se[ri+52>>2]=0|He.__str7,Se[ri+64>>2]=0|He.__str8,Se[ri+68>>2]=0|He.__str7,Se[ri+80>>2]=0|He.__str9,Se[ri+84>>2]=0|He.__str10,Se[ri+96>>2]=0|He.__str11,Se[ri+100>>2]=0|He.__str12,Se[ri+112>>2]=0|He.__str13,Se[ri+116>>2]=0|He.__str14,Se[ri+128>>2]=0|He.__str15,Se[ri+132>>2]=0|He.__str16,Se[ri+144>>2]=0|He.__str17,Se[ri+148>>2]=0|He.__str18,Se[ri+160>>2]=0|He.__str19,Se[ri+164>>2]=0|He.__str20,Se[ri+176>>2]=0|He.__str21,Se[ri+180>>2]=0|He.__str22,Se[ri+192>>2]=0|He.__str23,Se[ri+196>>2]=0|He.__str24,Se[ri+208>>2]=0|He.__str25,Se[ri+212>>2]=0|He.__str26,Se[ri+224>>2]=0|He.__str27,Se[ri+228>>2]=0|He.__str28,Se[ri+240>>2]=0|He.__str29,Se[ri+244>>2]=0|He.__str30,Se[ri+256>>2]=0|He.__str31,Se[ri+260>>2]=0|He.__str32,Se[ri+272>>2]=0|He.__str33,Se[ri+276>>2]=0|He.__str34,Se[ri+288>>2]=0|He.__str35,Se[ri+292>>2]=0|He.__str36,Se[ri+304>>2]=0|He.__str37,Se[ri+308>>2]=0|He.__str38,Se[ri+320>>2]=0|He.__str39,Se[ri+324>>2]=0|He.__str40,Se[ri+336>>2]=0|He.__str41,Se[ri+340>>2]=0|He.__str42,Se[ri+352>>2]=0|He.__str43,Se[ri+356>>2]=0|He.__str44,Se[ri+368>>2]=0|He.__str45,Se[ri+372>>2]=0|He.__str46,Se[ri+384>>2]=0|He.__str47,Se[ri+388>>2]=0|He.__str48,Se[ri+400>>2]=0|He.__str49,Se[ri+404>>2]=0|He.__str119289,Se[ri+416>>2]=0|He.__str51,Se[ri+420>>2]=0|He.__str20,Se[ri+432>>2]=0|He.__str52,Se[ri+436>>2]=0|He.__str53,Se[ri+448>>2]=0|He.__str54,Se[ri+452>>2]=0|He.__str55,Se[ri+464>>2]=0|He.__str56,Se[ri+468>>2]=0|He.__str57,Se[ri+480>>2]=0|He.__str58,Se[ri+484>>2]=0|He.__str119289,Se[ri+496>>2]=0|He.__str59,Se[ri+500>>2]=0|He.__str60,Se[ri+512>>2]=0|He.__str61,Se[ri+516>>2]=0|He.__str62,Se[ri+528>>2]=0|He.__str63,Se[ri+532>>2]=0|He.__str64,Se[ri+544>>2]=0|He.__str65,Se[ri+548>>2]=0|He.__str66,Se[ri+560>>2]=0|He.__str67,Se[ri+564>>2]=0|He.__str68,Se[ri+576>>2]=0|He.__str69,Se[ri+580>>2]=0|He.__str70,Se[ri+592>>2]=0|He.__str71,Se[ri+596>>2]=0|He.__str72,Se[ri+608>>2]=0|He.__str73,Se[ri+612>>2]=0|He.__str74,Se[ri+624>>2]=0|He.__str75,Se[ri+628>>2]=0|He.__str76,Se[ri+640>>2]=0|He.__str77,Se[ri+644>>2]=0|He.__str72,Se[ri+656>>2]=0|He.__str78,Se[ri+660>>2]=0|He.__str79,Se[ri+672>>2]=0|He.__str80,Se[ri+676>>2]=0|He.__str81,Se[ri+688>>2]=0|He.__str82,Se[ri+692>>2]=0|He.__str83,Se[ri+704>>2]=0|He.__str84,Se[ri+708>>2]=0|He.__str85,Se[ri+720>>2]=0|He.__str86,Se[ri+724>>2]=0|He.__str87,Se[ri+736>>2]=0|He.__str88,Se[ri+740>>2]=0|He.__str89,Se[ri+752>>2]=0|He.__str90,Se[ri+756>>2]=0|He.__str91,Se[ri+768>>2]=0|He.__str92,Se[ri+772>>2]=0|He.__str91,Se[ai>>2]=0|He.__str145315,Se[ai+8>>2]=0|He.__str145315,Se[ai+20>>2]=0|He.__str167337,Se[ai+28>>2]=0|He.__str95,Se[ai+40>>2]=0|He.__str146316,Se[ai+48>>2]=0|He.__str97,Se[ai+60>>2]=0|He.__str155325,Se[ai+68>>2]=0|He.__str155325,Se[ai+80>>2]=0|He.__str156326,Se[ai+88>>2]=0|He.__str156326,Se[ai+100>>2]=0|He.__str154324,Se[ai+108>>2]=0|He.__str154324,Se[ai+120>>2]=0|He.__str101,Se[ai+128>>2]=0|He.__str101,Se[ai+140>>2]=0|He.__str147317,Se[ai+148>>2]=0|He.__str147317,Se[ai+160>>2]=0|He.__str150320,Se[ai+168>>2]=0|He.__str150320,Se[ai+180>>2]=0|He.__str151321,Se[ai+188>>2]=0|He.__str105,Se[ai+220>>2]=0|He.__str152322,Se[ai+228>>2]=0|He.__str152322,Se[ai+240>>2]=0|He.__str153323,Se[ai+248>>2]=0|He.__str153323,Se[ai+260>>2]=0|He.__str165335,Se[ai+268>>2]=0|He.__str165335,Se[ai+280>>2]=0|He.__str166336,Se[ai+288>>2]=0|He.__str166336,Se[ai+360>>2]=0|He.__str148318,Se[ai+368>>2]=0|He.__str148318,Se[ai+380>>2]=0|He.__str149319,Se[ai+388>>2]=0|He.__str149319,Se[ai+420>>2]=0|He.__str84254,Se[ai+428>>2]=0|He.__str84254,Se[ai+440>>2]=0|He.__str168338,Se[ai+448>>2]=0|He.__str146316,Se[ai+460>>2]=0|He.__str114,Se[ai+468>>2]=0|He.__str152322,Se[ai+480>>2]=0|He.__str115,Se[ai+488>>2]=0|He.__str115,Se[ai+500>>2]=0|He.__str110280,Se[ai+508>>2]=0|He.__str110280,Se[ei+4>>2]=0|He.__str152,Se[ei+12>>2]=0|He.__str152,Se[ei+32>>2]=0|He.__str153,Se[ei+40>>2]=0|He.__str153,Se[ei+48>>2]=0|He.__str154,Se[ei+60>>2]=0|He.__str155,Se[ei+68>>2]=0|He.__str155,Se[ei+76>>2]=0|He.__str156,Se[ei+88>>2]=0|He.__str157,Se[ei+96>>2]=0|He.__str158,Se[ei+104>>2]=0|He.__str156,Se[ei+116>>2]=0|He.__str159,Se[ei+124>>2]=0|He.__str160,Se[ei+132>>2]=0|He.__str161,Se[ei+144>>2]=0|He.__str162,Se[ei+152>>2]=0|He.__str163,Se[ei+160>>2]=0|He.__str164,Se[ei+172>>2]=0|He.__str165,Se[ei+180>>2]=0|He.__str166,Se[ei+188>>2]=0|He.__str167,Se[si+4>>2]=bi,Se[ni+4>>2]=ki,oi=_([2,0,0,0,0],["i8*",0,0,0,0],we),Se[bi>>2]=oi+8|0,Se[bi+4>>2]=0|He.__ZTSSt9bad_alloc,Se[bi+8>>2]=li,Se[ki>>2]=oi+8|0,Se[ki+4>>2]=0|He.__ZTSSt20bad_array_new_length,Se[ki+8>>2]=bi,ui=16,ci=6,hi=18,di=6,wi=6,pe=[0,0,Jr,0,va,0,ya,0,ga,0,wa,0,Sa,0,pa,0,Ea,0,ma,0],Module.FUNCTION_TABLE=pe,Module.run=ee,Module.preRun&&Module.preRun(),0==Ke){ee()}Module.postRun&&Module.postRun(),Module.___cxa_demangle=G;var pi=v("__cxa_demangle","string",["string","string","number","number"]);return function(r){return pi(r,"",1,0)}}(); -` \ No newline at end of file diff --git a/src/speedscope/lib/file-format-spec.js b/src/speedscope/lib/file-format-spec.js deleted file mode 100644 index 9ac3e2fd6d701..0000000000000 --- a/src/speedscope/lib/file-format-spec.js +++ /dev/null @@ -1,13 +0,0 @@ -export var FileFormat; -(function (FileFormat) { - let ProfileType; - (function (ProfileType) { - ProfileType["EVENTED"] = "evented"; - ProfileType["SAMPLED"] = "sampled"; - })(ProfileType = FileFormat.ProfileType || (FileFormat.ProfileType = {})); - let EventType; - (function (EventType) { - EventType["OPEN_FRAME"] = "O"; - EventType["CLOSE_FRAME"] = "C"; - })(EventType = FileFormat.EventType || (FileFormat.EventType = {})); -})(FileFormat || (FileFormat = {})); diff --git a/src/speedscope/lib/flamechart.js b/src/speedscope/lib/flamechart.js deleted file mode 100644 index ad22e76fcc53b..0000000000000 --- a/src/speedscope/lib/flamechart.js +++ /dev/null @@ -1,137 +0,0 @@ -// @flow - -import type { Frame, CallTreeNode } from './profile' - -import { lastOf } from './utils'; -import { clamp } from './math'; - -export interface FlamechartFrame { - node: CallTreeNode; - start: number; - end: number; - parent: FlamechartFrame | null; - children: FlamechartFrame[]; -} - -type StackLayer = FlamechartFrame[]; - -interface FlamechartDataSource { - getTotalWeight(): number; - - formatValue(v: number): string; - - forEachCall( - openFrame: (node: CallTreeNode, value: number) => void, - closeFrame: (node: CallTreeNode, value: number) => void - ): void; - - getColorBucketForFrame(f: Frame): number; -} - -export class Flamechart { - source: FlamechartDataSource; - - // Bottom to top - layers: StackLayer[]; - totalWeight: number; - minFrameWidth: number; - - constructor(source: FlamechartDataSource) { - this.source = source; - - // Bottom to top - this.layers = []; - this.totalWeight = 0; - this.minFrameWidth = 1; - - const stack: FlamechartFrame[] = []; - const openFrame = (node, value) => { - const parent = lastOf(stack); - const frame = { - node, - parent, - children: [], - start: value, - end: value, - }; - if (parent) { - parent.children.push(frame); - } - stack.push(frame); - }; - this.minFrameWidth = Infinity; - const closeFrame = (node, value) => { - console.assert(stack.length > 0); - const stackTop = stack.pop(); - stackTop.end = value; - if (stackTop.end - stackTop.start === 0) return; - const layerIndex = stack.length; - while (this.layers.length <= layerIndex) this.layers.push([]); - this.layers[layerIndex].push(stackTop); - this.minFrameWidth = Math.min( - this.minFrameWidth, - stackTop.end - stackTop.start - ); - }; - this.totalWeight = source.getTotalWeight(); - source.forEachCall(openFrame, closeFrame); - if (!isFinite(this.minFrameWidth)) this.minFrameWidth = 1; - } - getTotalWeight() { - return this.totalWeight; - } - getLayers(): StackLayer[] { - return this.layers; - } - getColorBucketForFrame(frame: Frame) { - return this.source.getColorBucketForFrame(frame); - } - getMinFrameWidth() { - return this.minFrameWidth; - } - formatValue(v) { - return this.source.formatValue(v); - } - getClampedViewportWidth(viewportWidth: number) { - const maxWidth = this.getTotalWeight(); - // In order to avoid floating point error, we cap the maximum zoom. In - // particular, it's important that at the maximum zoom level, the total - // trace size + a viewport width is not equal to the trace size due to - // floating point rounding. - // - // For instance, if the profile's total weight is 2^60, and the viewport - // size is 1, trying to move one viewport width right will result in no - // change because 2^60 + 1 = 2^60 in floating point arithmetic. JavaScript - // numbers are 64 bit floats, and therefore have 53 mantissa bits. You can - // see this for yourself in the console. Try: - // - // > Math.pow(2, 60) + 1 === Math.pow(2, 60) - // true - // > Math.pow(2, 53) + 1 === Math.pow(2, 53) - // true - // > Math.pow(2, 52) + 1 === Math.pow(2, 52) - // false - // - // We use 2^40 as a cap instead, since we want to be able to make small - // adjustments within a viewport width. - // - // For reference, this will still allow you to zoom until 1 nanosecond fills - // the screen in a profile with a duration of over 18 minutes. - // - // > Math.pow(2, 40) / (60 * Math.pow(10, 9)) - // 18.325193796266667 - // - const maxZoom = Math.pow(2, 40); - // In addition to capping zoom to avoid floating point error, we further cap - // zoom to avoid letting you zoom in so that the smallest element more than - // fills the screen, since that probably isn't useful. The final zoom cap is - // determined by the minimum zoom of either 2^40x zoom or the necessary zoom - // for the smallest frame to fill the screen three times. - const minWidth = clamp( - 3 * this.getMinFrameWidth(), - maxWidth / maxZoom, - maxWidth - ); - return clamp(viewportWidth, minWidth, maxWidth); - } -} diff --git a/src/speedscope/lib/math.js b/src/speedscope/lib/math.js deleted file mode 100644 index 5f136c834939d..0000000000000 --- a/src/speedscope/lib/math.js +++ /dev/null @@ -1,302 +0,0 @@ -export function clamp(x, minVal, maxVal) { - if (x < minVal) - return minVal; - if (x > maxVal) - return maxVal; - return x; -} -export class Vec2 { - constructor(x, y) { - this.x = x; - this.y = y; - } - withX(x) { - return new Vec2(x, this.y); - } - withY(y) { - return new Vec2(this.x, y); - } - plus(other) { - return new Vec2(this.x + other.x, this.y + other.y); - } - minus(other) { - return new Vec2(this.x - other.x, this.y - other.y); - } - times(scalar) { - return new Vec2(this.x * scalar, this.y * scalar); - } - timesPointwise(other) { - return new Vec2(this.x * other.x, this.y * other.y); - } - dividedByPointwise(other) { - return new Vec2(this.x / other.x, this.y / other.y); - } - dot(other) { - return this.x * other.x + this.y * other.y; - } - equals(other) { - return this.x === other.x && this.y === other.y; - } - approxEquals(other, epsilon = 1e-9) { - return Math.abs(this.x - other.x) < epsilon && Math.abs(this.y - other.y) < epsilon; - } - length2() { - return this.dot(this); - } - length() { - return Math.sqrt(this.length2()); - } - abs() { - return new Vec2(Math.abs(this.x), Math.abs(this.y)); - } - static min(a, b) { - return new Vec2(Math.min(a.x, b.x), Math.min(a.y, b.y)); - } - static max(a, b) { - return new Vec2(Math.max(a.x, b.x), Math.max(a.y, b.y)); - } - static clamp(v, min, max) { - return new Vec2(clamp(v.x, min.x, max.x), clamp(v.y, min.y, max.y)); - } - flatten() { - return [this.x, this.y]; - } -} -Vec2.zero = new Vec2(0, 0); -Vec2.unit = new Vec2(1, 1); -export class AffineTransform { - constructor(m00 = 1, m01 = 0, m02 = 0, m10 = 0, m11 = 1, m12 = 0) { - this.m00 = m00; - this.m01 = m01; - this.m02 = m02; - this.m10 = m10; - this.m11 = m11; - this.m12 = m12; - } - withScale(s) { - let { m00, m01, m02, m10, m11, m12 } = this; - m00 = s.x; - m11 = s.y; - return new AffineTransform(m00, m01, m02, m10, m11, m12); - } - static withScale(s) { - return new AffineTransform().withScale(s); - } - scaledBy(s) { - return AffineTransform.withScale(s).times(this); - } - getScale() { - return new Vec2(this.m00, this.m11); - } - withTranslation(t) { - let { m00, m01, m02, m10, m11, m12 } = this; - m02 = t.x; - m12 = t.y; - return new AffineTransform(m00, m01, m02, m10, m11, m12); - } - static withTranslation(t) { - return new AffineTransform().withTranslation(t); - } - getTranslation() { - return new Vec2(this.m02, this.m12); - } - translatedBy(t) { - return AffineTransform.withTranslation(t).times(this); - } - static betweenRects(from, to) { - return AffineTransform.withTranslation(from.origin.times(-1)) - .scaledBy(new Vec2(to.size.x / from.size.x, to.size.y / from.size.y)) - .translatedBy(to.origin); - } - times(other) { - const m00 = this.m00 * other.m00 + this.m01 * other.m10; - const m01 = this.m00 * other.m01 + this.m01 * other.m11; - const m02 = this.m00 * other.m02 + this.m01 * other.m12 + this.m02; - const m10 = this.m10 * other.m00 + this.m11 * other.m10; - const m11 = this.m10 * other.m01 + this.m11 * other.m11; - const m12 = this.m10 * other.m02 + this.m11 * other.m12 + this.m12; - return new AffineTransform(m00, m01, m02, m10, m11, m12); - } - equals(other) { - return (this.m00 == other.m00 && - this.m01 == other.m01 && - this.m02 == other.m02 && - this.m10 == other.m10 && - this.m11 == other.m11 && - this.m12 == other.m12); - } - approxEquals(other, epsilon = 1e-9) { - return (Math.abs(this.m00 - other.m00) < epsilon && - Math.abs(this.m01 - other.m01) < epsilon && - Math.abs(this.m02 - other.m02) < epsilon && - Math.abs(this.m10 - other.m10) < epsilon && - Math.abs(this.m11 - other.m11) < epsilon && - Math.abs(this.m12 - other.m12) < epsilon); - } - timesScalar(s) { - const { m00, m01, m02, m10, m11, m12 } = this; - return new AffineTransform(s * m00, s * m01, s * m02, s * m10, s * m11, s * m12); - } - det() { - const { m00, m01, m02, m10, m11, m12 } = this; - const m20 = 0; - const m21 = 0; - const m22 = 1; - return (m00 * (m11 * m22 - m12 * m21) - m01 * (m10 * m22 - m12 * m20) + m02 * (m10 * m21 - m11 * m20)); - } - adj() { - const { m00, m01, m02, m10, m11, m12 } = this; - const m20 = 0; - const m21 = 0; - const m22 = 1; - // Adjugate matrix (a) is the transpose of the - // cofactor matrix (c). - // - // 00 01 02 - // 10 11 12 - // 20 21 22 - const a00 = /* c00 = */ +(m11 * m22 - m12 * m21); - const a01 = /* c10 = */ -(m01 * m22 - m02 * m21); - const a02 = /* c20 = */ +(m01 * m12 - m02 * m11); - const a10 = /* c01 = */ -(m10 * m22 - m12 * m20); - const a11 = /* c11 = */ +(m00 * m22 - m02 * m20); - const a12 = /* c21 = */ -(m00 * m12 - m02 * m10); - return new AffineTransform(a00, a01, a02, a10, a11, a12); - } - inverted() { - const det = this.det(); - if (det === 0) - return null; - const adj = this.adj(); - return adj.timesScalar(1 / det); - } - transformVector(v) { - return new Vec2(v.x * this.m00 + v.y * this.m01, v.x * this.m10 + v.y * this.m11); - } - inverseTransformVector(v) { - const inv = this.inverted(); - if (!inv) - return null; - return inv.transformVector(v); - } - transformPosition(v) { - return new Vec2(v.x * this.m00 + v.y * this.m01 + this.m02, v.x * this.m10 + v.y * this.m11 + this.m12); - } - inverseTransformPosition(v) { - const inv = this.inverted(); - if (!inv) - return null; - return inv.transformPosition(v); - } - transformRect(r) { - const size = this.transformVector(r.size); - const origin = this.transformPosition(r.origin); - if (size.x < 0 && size.y < 0) { - return new Rect(origin.plus(size), size.abs()); - } - else if (size.x < 0) { - return new Rect(origin.withX(origin.x + size.x), size.abs()); - } - else if (size.y < 0) { - return new Rect(origin.withY(origin.y + size.y), size.abs()); - } - return new Rect(origin, size); - } - inverseTransformRect(r) { - const inv = this.inverted(); - if (!inv) - return null; - return inv.transformRect(r); - } - flatten() { - // Flatten into GLSL format - // prettier-ignore - return [ - this.m00, this.m10, 0, - this.m01, this.m11, 0, - this.m02, this.m12, 1, - ]; - } -} -export class Rect { - constructor(origin, size) { - this.origin = origin; - this.size = size; - } - isEmpty() { - return this.width() == 0 || this.height() == 0; - } - width() { - return this.size.x; - } - height() { - return this.size.y; - } - left() { - return this.origin.x; - } - right() { - return this.left() + this.width(); - } - top() { - return this.origin.y; - } - bottom() { - return this.top() + this.height(); - } - topLeft() { - return this.origin; - } - topRight() { - return this.origin.plus(new Vec2(this.width(), 0)); - } - bottomRight() { - return this.origin.plus(this.size); - } - bottomLeft() { - return this.origin.plus(new Vec2(0, this.height())); - } - withOrigin(origin) { - return new Rect(origin, this.size); - } - withSize(size) { - return new Rect(this.origin, size); - } - closestPointTo(p) { - return new Vec2(clamp(p.x, this.left(), this.right()), clamp(p.y, this.top(), this.bottom())); - } - distanceFrom(p) { - return p.minus(this.closestPointTo(p)).length(); - } - contains(p) { - return this.distanceFrom(p) === 0; - } - hasIntersectionWith(other) { - const top = Math.max(this.top(), other.top()); - const bottom = Math.max(top, Math.min(this.bottom(), other.bottom())); - if (bottom - top === 0) - return false; - const left = Math.max(this.left(), other.left()); - const right = Math.max(left, Math.min(this.right(), other.right())); - if (right - left === 0) - return false; - return true; - } - intersectWith(other) { - const topLeft = Vec2.max(this.topLeft(), other.topLeft()); - const bottomRight = Vec2.max(topLeft, Vec2.min(this.bottomRight(), other.bottomRight())); - return new Rect(topLeft, bottomRight.minus(topLeft)); - } - equals(other) { - return this.origin.equals(other.origin) && this.size.equals(other.size); - } - approxEquals(other) { - return this.origin.approxEquals(other.origin) && this.size.approxEquals(other.size); - } - area() { - return this.size.x * this.size.y; - } -} -Rect.empty = new Rect(Vec2.zero, Vec2.zero); -Rect.unit = new Rect(Vec2.zero, Vec2.unit); -Rect.NDC = new Rect(new Vec2(-1, -1), new Vec2(2, 2)); diff --git a/src/speedscope/lib/profile.js b/src/speedscope/lib/profile.js deleted file mode 100644 index d83a5e8fca2f9..0000000000000 --- a/src/speedscope/lib/profile.js +++ /dev/null @@ -1,604 +0,0 @@ -// @flow - -import { lastOf, KeyedSet } from './utils'; -import { ValueFormatter, RawValueFormatter } from './value-formatters'; -import { FileFormat } from './file-format-spec'; -const demangleCppModule = import('./demangle-cpp'); - -// Force eager loading of the module -demangleCppModule.then(() => {}); - -export class HasWeights { - constructor() { - this.selfWeight = 0; - this.totalWeight = 0; - } - getSelfWeight() { - return this.selfWeight; - } - getTotalWeight() { - return this.totalWeight; - } - addToTotalWeight(delta) { - this.totalWeight += delta; - } - addToSelfWeight(delta) { - this.selfWeight += delta; - } - overwriteWeightWith(other) { - this.selfWeight = other.selfWeight; - this.totalWeight = other.totalWeight; - } -} - -export class Frame extends HasWeights { - static root: Frame; - - key: string | number; - - /** - * Name of the frame. May be a method name, e.g. "ActiveRecord##to_hash" - */ - name: string; - - /** - * File path of the code corresponding to this call stack frame. - */ - file: ?string; - - /** - * Line in the given file where this frame occurs - */ - line: ?number; - - /** - * Column in the file - */ - col: ?number; - - constructor(info) { - super(); - this.key = info.key; - this.name = info.name; - this.file = info.file; - this.line = info.line; - this.col = info.col; - } - static getOrInsert(set, info) { - return set.getOrInsert(new Frame(info)); - } -} - -Frame.root = new Frame({ - key: '(speedscope root)', - name: '(speedscope root)', -}); - -export class CallTreeNode extends HasWeights { - frame: Frame; - - children: CallTreeNode[]; - frozen: boolean; - - constructor(frame: Frame, parent) { - super(); - this.frame = frame; - this.parent = parent; - this.children = []; - // If a node is "frozen", it means it should no longer be mutated. - this.frozen = false; - } - isRoot() { - return this.frame === Frame.root; - } - isFrozen() { - return this.frozen; - } - freeze() { - this.frozen = true; - } -} - -export interface ProfileGroup { - name: string; - indexToView: number; - profiles: Profile[]; -} - -export class Profile { - name: string; - totalWeight: number; - frames: KeyedSet; - - appendOrderCalltreeRoot: CallTreeNode; - groupedCalltreeRoot: CallTreeNode; - - // List of references to CallTreeNodes at the top of the - // stack at the time of the sample. - samples: CallTreeNode[]; - weights: number[]; - - valueFormatter: ValueFormatter; - - totalNonIdleWeight: number | null; - - constructor(totalWeight: number = 0) { - this.name = ''; - this.frames = new KeyedSet(); - this.appendOrderCalltreeRoot = new CallTreeNode(Frame.root, null); - this.groupedCalltreeRoot = new CallTreeNode(Frame.root, null); - // List of references to CallTreeNodes at the top of the - // stack at the time of the sample. - this.samples = []; - this.weights = []; - this.valueFormatter = new RawValueFormatter(); - this.totalNonIdleWeight = null; - this.totalWeight = totalWeight; - } - getAppendOrderCalltreeRoot() { - return this.appendOrderCalltreeRoot; - } - getGroupedCalltreeRoot() { - return this.groupedCalltreeRoot; - } - formatValue(v: number) { - return this.valueFormatter.format(v); - } - setValueFormatter(f: ValueFormatter) { - this.valueFormatter = f; - } - getWeightUnit() { - return this.valueFormatter.unit; - } - getName() { - return this.name; - } - setName(name: string) { - this.name = name; - } - getTotalWeight() { - return this.totalWeight; - } - getTotalNonIdleWeight() { - if (this.totalNonIdleWeight === null) { - this.totalNonIdleWeight = this.groupedCalltreeRoot.children.reduce( - (n, c) => n + c.getTotalWeight(), - 0 - ); - } - return this.totalNonIdleWeight; - } - forEachCallGrouped( - openFrame: (node: CallTreeNode, value: number) => void, - closeFrame: (node: CallTreeNode, value: number) => void - ) { - function visit(node, start) { - if (node.frame !== Frame.root) { - openFrame(node, start); - } - let childTime = 0; - const children = [...node.children]; - children.sort((a, b) => - a.getTotalWeight() > b.getTotalWeight() ? -1 : 1 - ); - children.forEach(function(child) { - visit(child, start + childTime); - childTime += child.getTotalWeight(); - }); - if (node.frame !== Frame.root) { - closeFrame(node, start + node.getTotalWeight()); - } - } - visit(this.groupedCalltreeRoot, 0); - } - forEachCall( - openFrame: (node: CallTreeNode, value: number) => void, - closeFrame: (node: CallTreeNode, value: number) => void - ) { - let prevStack = []; - let value = 0; - let sampleIndex = 0; - for (let stackTop of this.samples) { - // Find lowest common ancestor of the current stack and the previous one - let lca = null; - // This is O(n^2), but n should be relatively small here (stack height), - // so hopefully this isn't much of a problem - for ( - lca = stackTop; - lca && lca.frame != Frame.root && prevStack.indexOf(lca) === -1; - lca = lca.parent - ) {} - // Close frames that are no longer open - while (prevStack.length > 0 && lastOf(prevStack) != lca) { - const node = prevStack.pop(); - closeFrame(node, value); - } - // Open frames that are now becoming open - const toOpen = []; - for ( - let node = stackTop; - node && node.frame != Frame.root && node != lca; - node = node.parent - ) { - toOpen.push(node); - } - toOpen.reverse(); - for (let node of toOpen) { - openFrame(node, value); - } - prevStack = prevStack.concat(toOpen); - value += this.weights[sampleIndex++]; - } - // Close frames that are open at the end of the trace - for (let i = prevStack.length - 1; i >= 0; i--) { - closeFrame(prevStack[i], value); - } - } - forEachFrame(fn: (frame: Frame) => void) { - this.frames.forEach(fn); - } - forEachSample(fn: (sample: CallTreeNode, weight: number) => void) { - for (let i = 0; i < this.samples.length; i++) { - fn(this.samples[i], this.weights[i]); - } - } - getProfileWithRecursionFlattened() { - const builder = new CallTreeProfileBuilder(); - const stack = []; - const framesInStack = new Set(); - function openFrame(node, value) { - if (framesInStack.has(node.frame)) { - stack.push(null); - } else { - framesInStack.add(node.frame); - stack.push(node); - builder.enterFrame(node.frame, value); - } - } - function closeFrame(node, value) { - const stackTop = stack.pop(); - if (stackTop) { - framesInStack.delete(stackTop.frame); - builder.leaveFrame(stackTop.frame, value); - } - } - this.forEachCall(openFrame, closeFrame); - const flattenedProfile = builder.build(); - flattenedProfile.name = this.name; - flattenedProfile.valueFormatter = this.valueFormatter; - // When constructing a profile with recursion flattened, - // counter-intuitive things can happen to "self time" measurements - // for functions. - // For example, given the following list of stacks w/ weights: - // - // a 1 - // a;b;a 1 - // a;b;a;b;a 1 - // a;b;a 1 - // - // The resulting profile with recursion flattened out will look like this: - // - // a 1 - // a;b 3 - // - // Which is useful to view, but it's counter-intuitive to move self-time - // for frames around, since analyzing the self-time of functions is an important - // thing to be able to do accurately, and we don't want this to change when recursion - // is flattened. To work around that, we'll just copy the weights directly from the - // un-flattened profile. - this.forEachFrame(f => { - flattenedProfile.frames.getOrInsert(f).overwriteWeightWith(f); - }); - return flattenedProfile; - } - getInvertedProfileForCallersOf(focalFrameInfo) { - const focalFrame = Frame.getOrInsert(this.frames, focalFrameInfo); - const builder = new StackListProfileBuilder(); - // TODO(jlfwong): Could construct this at profile - // construction time rather than on demand. - const nodes = []; - function visit(node) { - if (node.frame === focalFrame) { - nodes.push(node); - } else { - for (let child of node.children) { - visit(child); - } - } - } - visit(this.appendOrderCalltreeRoot); - for (let node of nodes) { - const stack = []; - for (let n = node; n != null && n.frame !== Frame.root; n = n.parent) { - stack.push(n.frame); - } - builder.appendSampleWithWeight(stack, node.getTotalWeight()); - } - const ret = builder.build(); - ret.name = this.name; - ret.valueFormatter = this.valueFormatter; - return ret; - } - getProfileForCalleesOf(focalFrameInfo) { - const focalFrame = Frame.getOrInsert(this.frames, focalFrameInfo); - const builder = new StackListProfileBuilder(); - function recordSubtree(focalFrameNode) { - const stack = []; - function visit(node) { - stack.push(node.frame); - builder.appendSampleWithWeight(stack, node.getSelfWeight()); - for (let child of node.children) { - visit(child); - } - stack.pop(); - } - visit(focalFrameNode); - } - function findCalls(node) { - if (node.frame === focalFrame) { - recordSubtree(node); - } else { - for (let child of node.children) { - findCalls(child); - } - } - } - findCalls(this.appendOrderCalltreeRoot); - const ret = builder.build(); - ret.name = this.name; - ret.valueFormatter = this.valueFormatter; - return ret; - } - // Demangle symbols for readability - async demangle() { - let demangleCpp = null; - for (let frame of this.frames) { - // This function converts a mangled C++ name such as "__ZNK7Support6ColorFeqERKS0_" - // into a human-readable symbol (in this case "Support::ColorF::==(Support::ColorF&)") - if (frame.name.startsWith('__Z')) { - if (!demangleCpp) { - demangleCpp = (await demangleCppModule).demangleCpp; - } - frame.name = demangleCpp(frame.name); - } - } - } - remapNames(callback) { - for (let frame of this.frames) { - frame.name = callback(frame.name); - } - } -} -export class StackListProfileBuilder extends Profile { - constructor() { - super(...arguments); - this.pendingSample = null; - } - _appendSample(stack, weight, useAppendOrder) { - if (isNaN(weight)) throw new Error('invalid weight'); - let node = useAppendOrder - ? this.appendOrderCalltreeRoot - : this.groupedCalltreeRoot; - let framesInStack = new Set(); - for (let frameInfo of stack) { - const frame = Frame.getOrInsert(this.frames, frameInfo); - const last = useAppendOrder - ? lastOf(node.children) - : node.children.find(c => c.frame === frame); - if (last && !last.isFrozen() && last.frame == frame) { - node = last; - } else { - const parent = node; - node = new CallTreeNode(frame, node); - parent.children.push(node); - } - node.addToTotalWeight(weight); - // It's possible for the same frame to occur multiple - // times in the same call stack due to either direct - // or indirect recursion. We want to avoid counting that - // frame multiple times for a single sample, we so just - // track all of the unique frames that participated in - // this call stack, then add to their weight at the end. - framesInStack.add(node.frame); - } - node.addToSelfWeight(weight); - if (useAppendOrder) { - for (let child of node.children) { - child.freeze(); - } - } - if (useAppendOrder) { - node.frame.addToSelfWeight(weight); - for (let frame of framesInStack) { - frame.addToTotalWeight(weight); - } - if (node === lastOf(this.samples)) { - this.weights[this.weights.length - 1] += weight; - } else { - this.samples.push(node); - this.weights.push(weight); - } - } - } - appendSampleWithWeight(stack, weight) { - if (weight === 0) { - // Samples with zero weight have no effect, so let's ignore them - return; - } - if (weight < 0) { - throw new Error('Samples must have positive weights'); - } - this._appendSample(stack, weight, true); - this._appendSample(stack, weight, false); - } - appendSampleWithTimestamp(stack, timestamp) { - if (this.pendingSample) { - if (timestamp < this.pendingSample.centralTimestamp) { - throw new Error('Timestamps received out of order'); - } - const endTimestamp = - (timestamp + this.pendingSample.centralTimestamp) / 2; - this.appendSampleWithWeight( - this.pendingSample.stack, - endTimestamp - this.pendingSample.startTimestamp - ); - this.pendingSample = { - stack, - startTimestamp: endTimestamp, - centralTimestamp: timestamp, - }; - } else { - this.pendingSample = { - stack, - startTimestamp: timestamp, - centralTimestamp: timestamp, - }; - } - } - build() { - if (this.pendingSample) { - if (this.samples.length > 0) { - this.appendSampleWithWeight( - this.pendingSample.stack, - this.pendingSample.centralTimestamp - - this.pendingSample.startTimestamp - ); - } else { - // There is only a single sample. In this case, units will be meaningless, - // so we'll append with a weight of 1 and also clear any value formatter - this.appendSampleWithWeight(this.pendingSample.stack, 1); - this.setValueFormatter(new RawValueFormatter()); - } - } - this.totalWeight = Math.max( - this.totalWeight, - this.weights.reduce((a, b) => a + b, 0) - ); - return this; - } -} -// As an alternative API for importing profiles more efficiently, provide a -// way to open & close frames directly without needing to construct tons of -// arrays as intermediaries. -export class CallTreeProfileBuilder extends Profile { - constructor() { - super(...arguments); - this.appendOrderStack = [this.appendOrderCalltreeRoot]; - this.groupedOrderStack = [this.groupedCalltreeRoot]; - this.framesInStack = new Map(); - this.stack = []; - this.lastValue = 0; - } - addWeightsToFrames(value) { - const delta = value - this.lastValue; - for (let frame of this.framesInStack.keys()) { - frame.addToTotalWeight(delta); - } - const stackTop = lastOf(this.stack); - if (stackTop) { - stackTop.addToSelfWeight(delta); - } - } - addWeightsToNodes(value, stack) { - const delta = value - this.lastValue; - for (let node of stack) { - node.addToTotalWeight(delta); - } - const stackTop = lastOf(stack); - if (stackTop) { - stackTop.addToSelfWeight(delta); - } - } - _enterFrame(frame, value, useAppendOrder) { - let stack = useAppendOrder ? this.appendOrderStack : this.groupedOrderStack; - this.addWeightsToNodes(value, stack); - let prevTop = lastOf(stack); - if (prevTop) { - if (useAppendOrder) { - const delta = value - this.lastValue; - if (delta > 0) { - this.samples.push(prevTop); - this.weights.push(value - this.lastValue); - } else if (delta < 0) { - throw new Error( - `Samples must be provided in increasing order of cumulative value. Last sample was ${this.lastValue}, this sample was ${value}` - ); - } - } - const last = useAppendOrder - ? lastOf(prevTop.children) - : prevTop.children.find(c => c.frame === frame); - let node; - if (last && !last.isFrozen() && last.frame == frame) { - node = last; - } else { - node = new CallTreeNode(frame, prevTop); - prevTop.children.push(node); - } - stack.push(node); - } - } - enterFrame(frameInfo, value) { - const frame = Frame.getOrInsert(this.frames, frameInfo); - this.addWeightsToFrames(value); - this._enterFrame(frame, value, true); - this._enterFrame(frame, value, false); - this.stack.push(frame); - const frameCount = this.framesInStack.get(frame) || 0; - this.framesInStack.set(frame, frameCount + 1); - this.lastValue = value; - } - _leaveFrame(frame, value, useAppendOrder) { - let stack = useAppendOrder ? this.appendOrderStack : this.groupedOrderStack; - this.addWeightsToNodes(value, stack); - if (useAppendOrder) { - const leavingStackTop = this.appendOrderStack.pop(); - if (leavingStackTop == null) { - throw new Error(`Trying to leave ${frame.key} when stack is empty`); - } - if (this.lastValue == null) { - throw new Error( - `Trying to leave a ${frame.key} before any have been entered` - ); - } - leavingStackTop.freeze(); - const delta = value - this.lastValue; - if (delta > 0) { - this.samples.push(leavingStackTop); - this.weights.push(value - this.lastValue); - } else if (delta < 0) { - throw new Error( - `Samples must be provided in increasing order of cumulative value. Last sample was ${this.lastValue}, this sample was ${value}` - ); - } - } else { - this.groupedOrderStack.pop(); - } - } - leaveFrame(frameInfo, value) { - const frame = Frame.getOrInsert(this.frames, frameInfo); - this.addWeightsToFrames(value); - this._leaveFrame(frame, value, true); - this._leaveFrame(frame, value, false); - this.stack.pop(); - const frameCount = this.framesInStack.get(frame); - if (frameCount == null) return; - if (frameCount === 1) { - this.framesInStack.delete(frame); - } else { - this.framesInStack.set(frame, frameCount - 1); - } - this.lastValue = value; - this.totalWeight = Math.max(this.totalWeight, this.lastValue); - } - build() { - // Each stack is expected to contain a single node which we initialize to be - // the root node. - if (this.appendOrderStack.length > 1 || this.groupedOrderStack.length > 1) { - throw new Error( - 'Tried to complete profile construction with a non-empty stack' - ); - } - return this; - } -} diff --git a/src/speedscope/lib/utils.js b/src/speedscope/lib/utils.js deleted file mode 100644 index e1923f8a10d29..0000000000000 --- a/src/speedscope/lib/utils.js +++ /dev/null @@ -1,254 +0,0 @@ -export function lastOf(ts) { - return ts[ts.length - 1] || null; -} -export function sortBy(ts, key) { - function comparator(a, b) { - return key(a) < key(b) ? -1 : 1; - } - ts.sort(comparator); -} -export function getOrInsert(map, k, fallback) { - if (!map.has(k)) - map.set(k, fallback(k)); - return map.get(k); -} -export function getOrElse(map, k, fallback) { - if (!map.has(k)) - return fallback(k); - return map.get(k); -} -export function getOrThrow(map, k) { - if (!map.has(k)) { - throw new Error(`Expected key ${k}`); - } - return map.get(k); -} -export class KeyedSet { - constructor() { - this.map = new Map(); - } - getOrInsert(t) { - const key = t.key; - const existing = this.map.get(key); - if (existing) - return existing; - this.map.set(key, t); - return t; - } - forEach(fn) { - this.map.forEach(fn); - } - [Symbol.iterator]() { - return this.map.values(); - } -} -export function* itMap(it, f) { - for (let t of it) { - yield f(t); - } -} -export function itForEach(it, f) { - for (let t of it) { - f(t); - } -} -export function itReduce(it, f, init) { - let accum = init; - for (let t of it) { - accum = f(accum, t); - } - return accum; -} -export function zeroPad(s, width) { - return new Array(Math.max(width - s.length, 0) + 1).join('0') + s; -} -export function formatPercent(percent) { - let formattedPercent = `${percent.toFixed(0)}%`; - if (percent === 100) - formattedPercent = '100%'; - else if (percent > 99) - formattedPercent = '>99%'; - else if (percent < 0.01) - formattedPercent = '<0.01%'; - else if (percent < 1) - formattedPercent = `${percent.toFixed(2)}%`; - else if (percent < 10) - formattedPercent = `${percent.toFixed(1)}%`; - return formattedPercent; -} -export function fract(x) { - return x - Math.floor(x); -} -export function triangle(x) { - return 2.0 * Math.abs(fract(x) - 0.5) - 1.0; -} -export function binarySearch(lo, hi, f, target, targetRangeSize = 1) { - console.assert(!isNaN(targetRangeSize) && !isNaN(target)); - while (true) { - if (hi - lo <= targetRangeSize) - return [lo, hi]; - const mid = (hi + lo) / 2; - const val = f(mid); - if (val < target) - lo = mid; - else - hi = mid; - } -} -export function noop(...args) { } -export function objectsHaveShallowEquality(a, b) { - for (let key in a) { - if (a[key] !== b[key]) - return false; - } - for (let key in b) { - if (a[key] !== b[key]) - return false; - } - return true; -} -export function memoizeByShallowEquality(cb) { - let last = null; - return (args) => { - let result; - if (last == null) { - result = cb(args); - last = { args, result }; - return result; - } - else if (objectsHaveShallowEquality(last.args, args)) { - return last.result; - } - else { - last.args = args; - last.result = cb(args); - return last.result; - } - }; -} -export function memoizeByReference(cb) { - let last = null; - return (args) => { - let result; - if (last == null) { - result = cb(args); - last = { args, result }; - return result; - } - else if (last.args === args) { - return last.result; - } - else { - last.args = args; - last.result = cb(args); - return last.result; - } - }; -} -export function lazyStatic(cb) { - let last = null; - return () => { - if (last == null) { - last = { result: cb() }; - } - return last.result; - }; -} -const base64lookupTable = lazyStatic(() => { - const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; - const ret = new Map(); - for (let i = 0; i < alphabet.length; i++) { - ret.set(alphabet.charAt(i), i); - } - ret.set('=', -1); - return ret; -}); -// NOTE: There are probably simpler solutions to this problem, but I have this written already, so -// until we run into problems with this, let's just use this. -// -// See: https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#The_Unicode_Problem#The_Unicode_Problem -export function decodeBase64(encoded) { - // Reference: https://www.rfc-editor.org/rfc/rfc4648.txt - const lookupTable = base64lookupTable(); - // 3 byte groups are represented as sequneces of 4 characters. - // - // "The encoding process represents 24-bit groups of input bits as output - // strings of 4 encoded characters." - // - // "Special processing is performed if fewer than 24 bits are available - // at the end of the data being encoded. A full encoding quantum is - // always completed at the end of a quantity. When fewer than 24 input - // bits are available in an input group bits with value zero are added - // (on the right) to form an integral number of 6-bit groups." - if (encoded.length % 4 !== 0) { - throw new Error(`Invalid length for base64 encoded string. Expected length % 4 = 0, got length = ${encoded.length}`); - } - const quartetCount = encoded.length / 4; - let byteCount; - // Special processing is performed if fewer than 24 bits are available - // at the end of the data being encoded. A full encoding quantum is - // always completed at the end of a quantity. When fewer than 24 input - // bits are available in an input group, bits with value zero are added - // (on the right) to form an integral number of 6-bit groups. Padding - // at the end of the data is performed using the '=' character. Since - // all base 64 input is an integral number of octets, only the following - // cases can arise: - // - // (1) The final quantum of encoding input is an integral multiple of 24 - // bits; here, the final unit of encoded output will be an integral - // multiple of 4 characters with no "=" padding. - // - // (2) The final quantum of encoding input is exactly 8 bits; here, the - // final unit of encoded output will be two characters followed by - // two "=" padding characters. - // - // (3) The final quantum of encoding input is exactly 16 bits; here, the - // final unit of encoded output will be three characters followed by - // one "=" padding character. - if (encoded.length >= 4) { - if (encoded.charAt(encoded.length - 1) === '=') { - if (encoded.charAt(encoded.length - 2) === '=') { - // Case (2) - byteCount = quartetCount * 3 - 2; - } - else { - // Case (3) - byteCount = quartetCount * 3 - 1; - } - } - else { - // Case (1) - byteCount = quartetCount * 3; - } - } - else { - // Case (1) - byteCount = quartetCount * 3; - } - const bytes = new Uint8Array(byteCount); - let offset = 0; - for (let i = 0; i < quartetCount; i++) { - const enc1 = encoded.charAt(i * 4 + 0); - const enc2 = encoded.charAt(i * 4 + 1); - const enc3 = encoded.charAt(i * 4 + 2); - const enc4 = encoded.charAt(i * 4 + 3); - const sextet1 = lookupTable.get(enc1); - const sextet2 = lookupTable.get(enc2); - const sextet3 = lookupTable.get(enc3); - const sextet4 = lookupTable.get(enc4); - if (sextet1 == null || sextet2 == null || sextet3 == null || sextet4 == null) { - throw new Error(`Invalid quartet at indices ${i * 4} .. ${i * 4 + 3}: ${encoded.substring(i * 4, i * 4 + 3)}`); - } - bytes[offset++] = (sextet1 << 2) | (sextet2 >> 4); - if (enc3 !== '=') { - bytes[offset++] = ((sextet2 & 15) << 4) | (sextet3 >> 2); - } - if (enc4 !== '=') { - bytes[offset++] = ((sextet3 & 7) << 6) | sextet4; - } - } - if (offset !== byteCount) { - throw new Error(`Expected to decode ${byteCount} bytes, but only decoded ${offset})`); - } - return bytes; -} diff --git a/src/speedscope/lib/value-formatters.js b/src/speedscope/lib/value-formatters.js deleted file mode 100644 index 089b490a6af0c..0000000000000 --- a/src/speedscope/lib/value-formatters.js +++ /dev/null @@ -1,59 +0,0 @@ -import {zeroPad} from './utils'; - -export class RawValueFormatter { - constructor() { - this.unit = 'none'; - } - format(v) { - return v.toLocaleString(); - } -} -export class TimeFormatter { - constructor(unit) { - this.unit = unit; - if (unit === 'nanoseconds') - this.multiplier = 1e-9; - else if (unit === 'microseconds') - this.multiplier = 1e-6; - else if (unit === 'milliseconds') - this.multiplier = 1e-3; - else - this.multiplier = 1; - } - formatUnsigned(v) { - const s = v * this.multiplier; - if (s / 60 >= 1) { - const minutes = Math.floor(s / 60); - const seconds = Math.floor(s - minutes * 60).toString(); - return `${minutes}:${zeroPad(seconds, 2)}`; - } - if (s / 1 >= 1) - return `${s.toFixed(2)}s`; - if (s / 1e-3 >= 1) - return `${(s / 1e-3).toFixed(2)}ms`; - if (s / 1e-6 >= 1) - return `${(s / 1e-6).toFixed(2)}µs`; - else - return `${(s / 1e-9).toFixed(2)}ns`; - } - format(v) { - return `${v < 0 ? '-' : ''}${this.formatUnsigned(Math.abs(v))}`; - } -} -export class ByteFormatter { - constructor() { - this.unit = 'bytes'; - } - format(v) { - if (v < 1024) - return `${v.toFixed(0)} B`; - v /= 1024; - if (v < 1024) - return `${v.toFixed(2)} KB`; - v /= 1024; - if (v < 1024) - return `${v.toFixed(2)} MB`; - v /= 1024; - return `${v.toFixed(2)} GB`; - } -} diff --git a/src/tracerbench/trace/bounds.js b/src/tracerbench/trace/bounds.js deleted file mode 100644 index f2ff80746f655..0000000000000 --- a/src/tracerbench/trace/bounds.js +++ /dev/null @@ -1,27 +0,0 @@ -import { TRACE_EVENT_PHASE_COMPLETE, TRACE_EVENT_PHASE_METADATA } from './trace_event'; -export default class Bounds { - constructor() { - this.min = 0; - this.max = 0; - this.empty = true; - } - addValue(value) { - if (this.empty) { - this.empty = false; - this.min = this.max = value; - } - else { - this.max = Math.max(this.max, value); - this.min = Math.min(this.min, value); - } - } - addEvent(event) { - if (event.ph === TRACE_EVENT_PHASE_METADATA) { - return; - } - this.addValue(event.ts); - if (event.ph === TRACE_EVENT_PHASE_COMPLETE) { - this.addValue(event.ts + event.dur); - } - } -} diff --git a/src/tracerbench/trace/cpu-profile.js b/src/tracerbench/trace/cpu-profile.js deleted file mode 100644 index 4b766e3a59df3..0000000000000 --- a/src/tracerbench/trace/cpu-profile.js +++ /dev/null @@ -1,316 +0,0 @@ -import { hierarchy } from 'd3-hierarchy'; -import { addRenderNodes } from './render-events'; -import { FUNCTION_NAME, TRACE_EVENT_NAME, TRACE_EVENT_PHASE_BEGIN, TRACE_EVENT_PHASE_END, TRACE_EVENT_PHASE_COMPLETE } from './trace_event'; -export default class CpuProfile { - constructor(profile, events, min, max) { - this.profile = profile; - const parentLinks = (this.parentLinks = new Map()); - const childrenLinks = (this.childrenLinks = new Map()); - const nodes = profile.nodes; - initNodes(nodes); - const nodeMap = mapAndLinkNodes(nodes, parentLinks, childrenLinks); - const originalRoot = nodes.find(node => { - return (node.callFrame.scriptId === 0 || - (node.callFrame.scriptId === '0' && - node.callFrame.functionName === FUNCTION_NAME.ROOT)); - }); - if (originalRoot === undefined) { - throw new Error('Missing root node in original profile'); - } - this.samples = absoluteSamples(profile, nodeMap); - const { expandedRoot, expandedNodeMap } = expandAndFix(this.samples, profile, events, min, max, parentLinks, childrenLinks, originalRoot); - this.root = expandedRoot; - this.nodeMap = expandedNodeMap; - const start = (this.start = profile.startTime); - const end = (this.end = expandedRoot.max); - this.duration = end - start; - this.hierarchy = hierarchy(expandedRoot, node => { - const children = childrenLinks.get(node); - if (children) { - return expandedRoot === node - ? children.filter(n => !isMetaNode(n)) - : children; - } - return null; - }); - // Make child iteration easier - this.hierarchy.each(node => { - if (node.children === undefined) { - node.children = []; - } - }); - addRenderNodes(this.hierarchy, events); - } - parent(node) { - return this.parentLinks.get(node); - } - children(node) { - return this.childrenLinks.get(node); - } - node(id) { - const n = this.nodeMap.get(id); - if (n === undefined) { - throw new Error(`invalid node id: ${id}`); - } - return n; - } -} -export function getChildren(node) { - if (node.children === undefined) { - throw new Error('Node had undefined children'); - } - return node.children; -} -function expandAndFix(samples, profile, events, min, max, parentLinks, childrenLinks, root) { - const { expandedNodes, orig2ExpNodes } = expandNodes(samples, events, min, max, parentLinks); - profile.nodes = expandedNodes; - parentLinks.clear(); - childrenLinks.clear(); - const expandedNodeMap = mapAndLinkNodes(expandedNodes, parentLinks, childrenLinks); - if (!orig2ExpNodes.has(root.id)) { - throw new Error('Missing root node in expanded profile'); - } - return { expandedRoot: orig2ExpNodes.get(root.id)[0], expandedNodeMap }; -} -function initNodes(nodes) { - for (let i = 0; i < nodes.length; i++) { - const node = nodes[i]; - // initialize our extensions - node.min = -1; - node.max = -1; - node.sampleCount = 0; - node.self = 0; - } -} -function mapAndLinkNodes(nodes, parentLinks, childrenLinks) { - const nodeMap = new Map(); - for (let i = 0; i < nodes.length; i++) { - nodeMap.set(nodes[i].id, nodes[i]); - } - linkNodes(nodes, nodeMap, parentLinks, childrenLinks); - return nodeMap; -} -function linkNodes(nodes, nodeMap, parentLinks, childrenLinks) { - for (let i = 0; i < nodes.length; i++) { - const node = nodes[i]; - linkChildren(node, nodeMap, parentLinks, childrenLinks); - } -} -function linkChildren(parent, nodeMap, parentLinks, childrenLinks) { - const childIds = parent.children; - if (childIds === undefined) { - return; - } - const children = new Array(childIds.length); - for (let i = 0; i < childIds.length; i++) { - const child = nodeMap.get(childIds[i]); - children[i] = child; - parentLinks.set(child, parent); - } - childrenLinks.set(parent, children); -} -function absoluteSamples(profile, nodeMap) { - const sampleIds = profile.samples; - const samples = new Array(sampleIds.length); - // deltas can be negative and samples out of order - const timeDeltas = profile.timeDeltas; - let last = profile.startTime; - for (let i = 0; i < sampleIds.length; i++) { - const node = nodeMap.get(sampleIds[i]); - const timestamp = last + timeDeltas[i]; - samples[i] = { - node, - delta: 0, - timestamp, - prev: null, - next: null, - }; - last = timestamp; - node.sampleCount++; - } - samples.sort((a, b) => a.timestamp - b.timestamp); - let prev = null; - for (let i = 0; i < samples.length; i++) { - const sample = samples[i]; - const timestamp = sample.timestamp; - if (prev === null) { - sample.delta = timestamp - profile.startTime; - } - else { - prev.next = sample; - sample.delta = timestamp - prev.timestamp; - sample.prev = prev; - } - prev = sample; - } - return samples; -} -function expandNodes(samples, events, min, max, parentLinks) { - const expandedNodes = []; - const orig2ExpNodes = new Map(); - const state = { - lastSampleTS: -1, - stack: [], - origId2activeIndex: new Map(), - expId2origId: new Map(), - }; - let begin; - let from = -1; - let to = -1; - let sampleIndex = 0; - let eventIndex = 0; - while (sampleIndex < samples.length) { - // move through events until we have an executing range - for (; eventIndex < events.length; eventIndex++) { - const event = events[eventIndex]; - if (begin !== undefined) { - if (event.ph === TRACE_EVENT_PHASE_END && - event.pid === begin.pid && - event.tid === begin.tid && - event.cat === begin.cat && - event.name === begin.name) { - begin = undefined; - to = event.ts; - } - } - else if (from === -1) { - if (event.name === TRACE_EVENT_NAME.V8_EXECUTE) { - if (event.ph === TRACE_EVENT_PHASE_BEGIN) { - begin = event; - from = event.ts; - to = -1; - } - else if (event.ph === TRACE_EVENT_PHASE_COMPLETE) { - from = event.ts; - to = event.ts + event.dur; - } - } - } - else if (event.ts > to) { - break; - } - } - // we should be just after `to` or out of events - // if we don't have a from/to then this will drain - // samples and exit - for (; sampleIndex < samples.length; sampleIndex++) { - // process samples in execute range - const sample = samples[sampleIndex]; - if (to !== -1 && sample.timestamp > to) { - // end executing - endExecute(state, to); - from = to = -1; - break; - } - else if (from !== -1 && - sample.timestamp > from && - !isOutOfBounds(sample.timestamp, min, max)) { - processSample(sample, orig2ExpNodes, parentLinks, expandedNodes, state); - } - } - // we should be just past a range or have no more samples - } - if (to !== -1) { - endExecute(state, to); - } - terminateNodes(state.stack, state.lastSampleTS, state); - return { expandedNodes, orig2ExpNodes }; -} -function isOutOfBounds(ts, min, max) { - return ts < min || (max !== -1 && ts > max); -} -function terminateNodes(toTerminate, ts, state) { - toTerminate.forEach(node => { - state.origId2activeIndex.delete(state.expId2origId.get(node.id)); - state.expId2origId.delete(node.id); - node.max = ts; - }); -} -function activateNodes(toActivate, state, ts, newNodes, orig2ExpNodes) { - const { stack, origId2activeIndex, expId2origId } = state; - let parent = stack[stack.length - 1]; - for (let i = toActivate.length - 1; i >= 0; i--) { - const oldNode = toActivate[i]; - // IProfileNode type gives access to the .parent attribute - const newNode = JSON.parse(JSON.stringify(oldNode)); - newNode.id = newNodes.length; - if (parent) { - newNode.parent = parent.id; - const children = parent.children; - if (children !== undefined) { - children.push(newNode.id); - } - else { - parent.children = [newNode.id]; - } - } - // clear out node-->children links - newNode.children = undefined; - newNode.min = ts; - newNode.max = -1; - newNode.self = 0; - newNode.total = 0; - newNodes.push(newNode); - stack.push(newNode); - origId2activeIndex.set(oldNode.id, stack.length - 1); - expId2origId.set(newNode.id, oldNode.id); - if (orig2ExpNodes.has(oldNode.id)) { - orig2ExpNodes.get(oldNode.id).push(newNode); - } - else { - orig2ExpNodes.set(oldNode.id, [newNode]); - } - parent = newNode; - } -} -function addDurationToNodes(stack, delta) { - if (stack.length > 0) { - stack[stack.length - 1].self += delta; - } -} -function endExecute(state, timestamp) { - const { stack, lastSampleTS } = state; - addDurationToNodes(stack, timestamp - lastSampleTS); - const toTerminate = stack.splice(1); // don't slice (root) - terminateNodes(toTerminate, timestamp, state); -} -function processSample(sample, orig2ExpNodes, parentLinks, newNodes, state) { - const { stack, origId2activeIndex } = state; - let curNode; - const toActivate = []; - state.lastSampleTS = sample.timestamp; - for (curNode = sample.node; curNode; curNode = parentLinks.get(curNode)) { - if (origId2activeIndex.has(curNode.id)) { - break; - } - toActivate.push(curNode); - } - addDurationToNodes(stack, sample.delta); - let spliceStart; - if (curNode === undefined) { - // No ongoing nodes, remove everything from the stack - spliceStart = 0; - } - else { - // Don't let GC or Program samples terminate the current stack - if (sample.node.callFrame.functionName === FUNCTION_NAME.GC || - sample.node.callFrame.functionName === FUNCTION_NAME.PROGRAM) { - spliceStart = stack.length; // no-op for slice - } - else { - // Leave only ongoing nodes on the stack - spliceStart = origId2activeIndex.get(curNode.id) + 1; - } - } - const toTerminate = stack.splice(spliceStart); - terminateNodes(toTerminate, sample.timestamp, state); - activateNodes(toActivate, state, sample.timestamp, newNodes, orig2ExpNodes); -} -export function isMetaNode(node) { - switch (node.callFrame.functionName) { - case FUNCTION_NAME.ROOT: - case FUNCTION_NAME.IDLE: - return true; - } - return false; -} diff --git a/src/tracerbench/trace/index.js b/src/tracerbench/trace/index.js deleted file mode 100644 index 3f291ed1dc780..0000000000000 --- a/src/tracerbench/trace/index.js +++ /dev/null @@ -1,10 +0,0 @@ -export { default as Bounds } from './bounds'; -export { default as Process } from './process'; -export { default as Trace } from './trace'; -export { default as Thread } from './thread'; -export { analyze, IAnalyze } from './analyze'; -export * from './archive_trace'; -export { loadTrace } from './load_trace'; -export { liveTrace } from './live_trace'; -export { networkConditions, IConditions, INetworkConditions, } from './conditions'; -export * from './trace_event'; diff --git a/src/tracerbench/trace/process.js b/src/tracerbench/trace/process.js deleted file mode 100644 index 209f83f136c81..0000000000000 --- a/src/tracerbench/trace/process.js +++ /dev/null @@ -1,26 +0,0 @@ -import Bounds from './bounds'; -import Thread from './thread'; -export default class Process { - constructor(id) { - this.id = id; - this.threads = []; - this.mainThread = null; - this.scriptStreamerThread = null; - this.bounds = new Bounds(); - this.events = []; - this.threadMap = {}; - } - thread(tid) { - let thread = this.threadMap[tid]; - if (thread === undefined) { - this.threadMap[tid] = thread = new Thread(tid); - this.threads.push(thread); - } - return thread; - } - addEvent(event) { - this.bounds.addEvent(event); - this.events.push(event); - this.thread(event.tid).addEvent(event); - } -} diff --git a/src/tracerbench/trace/render-events.js b/src/tracerbench/trace/render-events.js deleted file mode 100644 index 92af1b68b3765..0000000000000 --- a/src/tracerbench/trace/render-events.js +++ /dev/null @@ -1,138 +0,0 @@ -import binsearch from 'array-binsearch'; -import { getChildren } from './cpu-profile'; -import { TRACE_EVENT_PHASE_COMPLETE, TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN, } from './trace_event'; -const cloneDeep = require('lodash.clonedeep'); -export function addRenderNodes(hierarchy, events) { - events.forEach(event => { - if (!isRenderPhase(event)) { - return; - } - let found = null; - // Search for the closest node which fully encloses the render event - hierarchy.eachBefore((node) => { - if (nodeEnclosesEvent(node, event)) { - found = node; - } - }); - if (found) { - insertRenderEvent(found, event); - } - }); -} -function nodeEnclosesEvent(node, event) { - return (node.data.min !== -1 && - node.data.max !== -1 && - node.data.min < event.ts && - event.ts + event.dur < node.data.max); -} -function insertRenderEvent(enclosingNode, event) { - const eventStart = event.ts; - const eventEnd = event.ts + event.dur; - const renderNode = enclosingNode.copy(); - renderNode.data = { - id: -1, - callFrame: { - functionName: event.name, - scriptId: -1, - url: '', - lineNumber: -1, - columnNumber: -1, - }, - children: [], - sampleCount: -1, - min: eventStart, - max: eventEnd, - total: 0, - self: 0, - }; - const children = getChildren(enclosingNode); - // Children who are fully to the left or right of the render event - const childrenForOriginal = children.filter(child => child.data.max < eventStart || child.data.min > eventEnd); - // Children who are fully within the render event - const childrenForRenderNode = children.filter(child => child.data.min > eventStart && child.data.max < eventEnd); - // Children who are split by the render event - const leftSplitChild = children.find(n => n.data.min < eventStart && n.data.max > eventStart); - const rightSplitChild = children.find(n => n.data.min < eventEnd && n.data.max > eventEnd); - // Fix parent/child links for all children other then split children - enclosingNode.children = childrenForOriginal; - renderNode.children = childrenForRenderNode; - childrenForRenderNode.forEach(child => (child.parent = renderNode)); - // fix node/render node parent/child link - renderNode.parent = enclosingNode; - insertChildInOrder(enclosingNode.children, renderNode); - splitChild(enclosingNode, renderNode, leftSplitChild, eventStart); - splitChild(renderNode, enclosingNode, rightSplitChild, eventEnd); -} -function insertChildInOrder(children, node) { - let index = binsearch(children, node, (a, b) => a.data.min - b.data.min); - if (index < 0) { - /* tslint:disable:no-bitwise */ - index = ~index; - } - else { - // insert just after if ts order matched - index++; - } - children.splice(index, 0, node); -} -function splitChild(leftParent, rightParent, node, splitTS) { - if (node === undefined) { - return { middleLeftTime: 0, middleRightTime: 0 }; - } - // Split node - const left = node; - const right = node.copy(); - right.data = cloneDeep(node.data); - right.children = []; - left.data.max = splitTS; - right.data.min = splitTS; - // Add back in the child/parent links for the split node - left.parent = leftParent; - right.parent = rightParent; - insertChildInOrder(getChildren(leftParent), left); - insertChildInOrder(getChildren(rightParent), right); - const children = getChildren(node); - // If no further decendents, you are done - if (children.length === 0) { - left.data.self = left.data.max - left.data.min; - right.data.self = right.data.max - right.data.min; - return { middleLeftTime: left.data.self, middleRightTime: right.data.self }; - } - // Reasign children correctly - const middleChild = children.find(n => n.data.min < splitTS && n.data.max > splitTS); - const leftChildren = children.filter(child => child.data.max < left.data.max); - const rightChildren = children.filter(child => child.data.min > right.data.min); - left.children = leftChildren; - right.children = rightChildren; - // Start to sum self time of children - let leftChildrenTime = leftChildren.reduce((a, b) => a + b.data.self, 0); - let righChildrentTime = rightChildren.reduce((a, b) => a + b.data.self, 0); - // Split middle child and asign the resulting left/right node self times - const { middleLeftTime, middleRightTime } = splitChild(left, right, middleChild, splitTS); - leftChildrenTime += middleLeftTime; - righChildrentTime += middleRightTime; - left.data.self = left.data.max - left.data.min - leftChildrenTime; - right.data.self = right.data.max - right.data.min - righChildrentTime; - // Return the resulting left/right split times, so parents can determine their own self times - return { - middleLeftTime: left.data.max - left.data.min, - middleRightTime: right.data.max - right.data.min, - }; -} -export function isRenderEnd(event) { - return (event.ph === TRACE_EVENT_PHASE_NESTABLE_ASYNC_END && isRender(event.name)); -} -export function isRenderStart(event) { - return (event.ph === TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN && isRender(event.name)); -} -function isRenderPhase(event) { - return event.ph === TRACE_EVENT_PHASE_COMPLETE && isRender(event.name); -} -export function isRenderNode(node) { - return isRender(node.data.callFrame.functionName); -} -function isRender(name) { - return (name.endsWith('(Rendering: initial)') || - name.endsWith('(Rendering: update)') || - name.endsWith('(Rendering: outlet)')); -} diff --git a/src/tracerbench/trace/thread.js b/src/tracerbench/trace/thread.js deleted file mode 100644 index 410d19d69443a..0000000000000 --- a/src/tracerbench/trace/thread.js +++ /dev/null @@ -1,12 +0,0 @@ -import Bounds from './bounds'; -export default class Thread { - constructor(id) { - this.bounds = new Bounds(); - this.events = []; - this.id = id; - } - addEvent(event) { - this.bounds.addEvent(event); - this.events.push(event); - } -} diff --git a/src/tracerbench/trace/trace.js b/src/tracerbench/trace/trace.js deleted file mode 100644 index b16217224ffc1..0000000000000 --- a/src/tracerbench/trace/trace.js +++ /dev/null @@ -1,292 +0,0 @@ -/* tslint:disable:variable-name */ -/* tslint:disable:no-console */ -/* tslint:disable:no-bitwise */ -import binsearch from 'array-binsearch'; -import Bounds from './bounds'; -import Process from './process'; -import CpuProfile from './cpu-profile'; -import { isRenderEnd, isRenderStart } from './render-events'; -import { PROCESS_NAME, TRACE_EVENT_PHASE_BEGIN, TRACE_EVENT_PHASE_COMPLETE, TRACE_EVENT_PHASE_END, TRACE_EVENT_PHASE_METADATA, TRACE_EVENT_PHASE_SAMPLE, TRACE_EVENT_PHASE_INSTANT, } from './trace_event'; -import traceEventComparator from './trace_event_comparator'; -export default class Trace { - constructor() { - this.processes = []; - this.bounds = new Bounds(); - this.events = []; - this.browserProcess = null; - this.gpuProcess = null; - this.rendererProcesses = []; - this.parents = new Map(); - this.stack = []; - this.profileMap = new Map(); - } - cpuProfile(min, max) { - const { _cpuProfile } = this; - if (_cpuProfile === undefined) { - console.trace('public cpuProfile'); - throw new Error('trace is missing CpuProfile'); - } - return new CpuProfile(_cpuProfile, this.events, min, max); - } - process(pid) { - let process = this.findProcess(pid); - if (process === undefined) { - process = new Process(pid); - this.processes.push(process); - } - return process; - } - thread(pid, tid) { - return this.process(pid).thread(tid); - } - addEvents(events) { - for (const event of events) { - this.addEvent(event); - } - } - cpuProfileBuildModel(event) { - if (event.ph === TRACE_EVENT_PHASE_INSTANT && - event.cat === 'disabled-by-default-devtools.timeline') { - if (event.name === 'CpuProfile') { - this._cpuProfile = event.args.data.cpuProfile; - } - else if (event.name === 'TracingStartedInPage') { - this.lastTracingStartedInPageEvent = event; - } - } - else if (event.ph === TRACE_EVENT_PHASE_SAMPLE) { - if (event.name === 'Profile') { - const profile = event; - this.profileMap.set(profile.id, { - pid: profile.pid, - tid: profile.tid, - cpuProfile: { - startTime: profile.args.data.startTime, - endTime: 0, - duration: 0, - nodes: [], - samples: [], - timeDeltas: [], - }, - }); - } - else if (event.name === 'ProfileChunk') { - const profileChunk = event; - const profileEntry = this.profileMap.get(profileChunk.id); - if (profileChunk.args.data.cpuProfile.nodes) { - profileChunk.args.data.cpuProfile.nodes.forEach((node) => { - profileEntry.cpuProfile.nodes.push(Object.assign(node, { - sampleCount: 0, - min: 0, - max: 0, - total: 0, - self: 0, - })); - }); - } - profileEntry.cpuProfile.samples.push(...profileChunk.args.data.cpuProfile.samples); - profileEntry.cpuProfile.timeDeltas.push(...profileChunk.args.data.timeDeltas); - } - } - // determine main process - if (this.lastTracingStartedInPageEvent) { - // if this was recorded with the Performance tab, this should be the main process - this.mainProcess = this.process(this.lastTracingStartedInPageEvent.pid); - } - else { - // fallback to Renderer process with most events - this.mainProcess = this.processes - .filter(p => p.name === PROCESS_NAME.RENDERER) - .reduce((a, b) => (b.events.length > a.events.length ? b : a)); - } - for (const profileEntry of this.profileMap.values()) { - if (profileEntry.pid === this.mainProcess.id && - profileEntry.tid === this.mainProcess.mainThread.id) { - this._cpuProfile = profileEntry.cpuProfile; - const { nodes } = profileEntry.cpuProfile; - const nodeMap = new Map(); - nodes.forEach(node => nodeMap.set(node.id, node)); - nodes.forEach(node => { - if (node.parent !== undefined) { - const parent = nodeMap.get(node.parent); - if (!parent) { - return; // TODO Brian added this - } - if (parent.children) { - parent.children.push(node.id); - } - else { - parent.children = [node.id]; - } - } - }); - break; - } - } - } - buildModel() { - const { events } = this; - if (this.stack.length > 0) { - this.stack.length = 0; - } - for (const event of events) { - this.associateParent(event); - const process = this.process(event.pid); - process.addEvent(event); - this.cpuProfileBuildModel(event); - } - } - getParent(event) { - this.parents.get(event); - } - associateParent(event) { - if (event.ph !== TRACE_EVENT_PHASE_COMPLETE) { - return; - } - const { stack, parents } = this; - const { ts, pid, tid } = event; - - if (stack.length > 0) { // TODO Brian added this - for (let i = stack.length - 1; i >= 0; i--) { - const parent = stack[i]; - if (ts < parent.ts + parent.dur) { - if (parent.pid === pid && parent.tid === tid) { - parents.set(event, parent); - break; - } - } - else { - stack.splice(i, 1); - } - } - } // TODO Brian added this - stack.push(event); - } - addEvent(event) { - if (event.ph === TRACE_EVENT_PHASE_END || isRenderEnd(event)) { - this.endEvent(event); - return; - } - const events = this.events; - let index = binsearch(events, event, traceEventComparator); - if (index < 0) { - index = ~index; - } - else { - // insert just after if ts order matched - index++; - } - events.splice(index, 0, event); - if (event.ph === TRACE_EVENT_PHASE_METADATA) { - this.addMetadata(event); - return; - } - if (event.ph === TRACE_EVENT_PHASE_BEGIN || isRenderStart(event)) { - this.stack.push(event); - } - this.bounds.addEvent(event); - } - findProcess(pid) { - for (const process of this.processes) { - if (process.id === pid) { - return process; - } - } - return; - } - endEvent(end) { - const { stack } = this; - for (let i = stack.length - 1; i >= 0; i--) { - const begin = stack[i]; - if (begin.name === end.name && - begin.cat === end.cat && - begin.tid === end.tid && - begin.pid === end.pid) { - stack.splice(i, 1); - return this.completeEvent(begin, end); - } - } - throw new Error('could not find matching B phase for E phase event'); - } - completeEvent(begin, end) { - let args = '__stripped__'; - if (typeof begin.args === 'object' && begin.args !== null) { - args = Object.assign({}, begin.args); - } - if (typeof end.args === 'object' && end.args !== null) { - args = Object.assign(args === undefined ? {} : args, end.args); - } - const complete = { - args, - cat: begin.cat, - dur: end.ts - begin.ts, - name: begin.name, - ph: TRACE_EVENT_PHASE_COMPLETE, - pid: begin.pid, - tdur: end.tts - begin.tts, - tid: begin.tid, - ts: begin.ts, - tts: begin.tts, - }; - const { events } = this; - const index = binsearch(events, begin, traceEventComparator); - events[index] = complete; - } - addMetadata(event) { - const { pid, tid } = event; - if (event.args === '__stripped__') { - return; - } - switch (event.name) { - case 'num_cpus': - this.numberOfProcessors = event.args.number; - break; - case 'process_name': - const processName = event.args.name; - const process = this.process(pid); - process.name = processName; - if (processName === 'GPU Process') { - this.gpuProcess = process; - } - else if (processName === 'Browser') { - this.browserProcess = process; - } - else if (processName === 'Renderer') { - this.rendererProcesses.push(process); - } - break; - case 'process_labels': - this.process(pid).labels = event.args.labels; - break; - case 'process_sort_index': - this.process(pid).sortIndex = event.args.sort_index; - break; - case 'trace_buffer_overflowed': - this.process(pid).traceBufferOverflowedAt = event.args.overflowed_at_ts; - break; - case 'thread_name': - const threadName = event.args.name; - const thread = this.thread(pid, tid); - thread.name = threadName; - if (threadName === 'CrRendererMain') { - this.process(pid).mainThread = thread; - } - else if (threadName === 'ScriptStreamerThread') { - this.process(pid).scriptStreamerThread = thread; - } - break; - case 'thread_sort_index': - this.thread(pid, tid).sortIndex = event.args.sort_index; - break; - case 'IsTimeTicksHighResolution': - this.process(pid).isTimeTicksHighResolution = event.args.value; - break; - case 'TraceConfig': - this.process(pid).traceConfig = event.args.value; - break; - default: - // console.warn("unrecognized metadata:", JSON.stringify(event, null, 2)); - break; - } - } -} diff --git a/src/tracerbench/trace/trace_event.js b/src/tracerbench/trace/trace_event.js deleted file mode 100644 index 8d9c0499d3c05..0000000000000 --- a/src/tracerbench/trace/trace_event.js +++ /dev/null @@ -1,54 +0,0 @@ -export const TRACE_EVENT_PHASE_BEGIN = 'B'; -export const TRACE_EVENT_PHASE_END = 'E'; -export const TRACE_EVENT_PHASE_COMPLETE = 'X'; -export const TRACE_EVENT_PHASE_INSTANT = 'I'; -export const TRACE_EVENT_PHASE_ASYNC_BEGIN = 'S'; -export const TRACE_EVENT_PHASE_ASYNC_STEP_INTO = 'T'; -export const TRACE_EVENT_PHASE_ASYNC_STEP_PAST = 'p'; -export const TRACE_EVENT_PHASE_ASYNC_END = 'F'; -export const TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN = 'b'; -export const TRACE_EVENT_PHASE_NESTABLE_ASYNC_END = 'e'; -export const TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT = 'n'; -export const TRACE_EVENT_PHASE_FLOW_BEGIN = 's'; -export const TRACE_EVENT_PHASE_FLOW_STEP = 't'; -export const TRACE_EVENT_PHASE_FLOW_END = 'f'; -export const TRACE_EVENT_PHASE_METADATA = 'M'; -export const TRACE_EVENT_PHASE_COUNTER = 'C'; -export const TRACE_EVENT_PHASE_SAMPLE = 'P'; -export const TRACE_EVENT_PHASE_CREATE_OBJECT = 'N'; -export const TRACE_EVENT_PHASE_SNAPSHOT_OBJECT = 'O'; -export const TRACE_EVENT_PHASE_DELETE_OBJECT = 'D'; -export const TRACE_EVENT_PHASE_MEMORY_DUMP = 'v'; -export const TRACE_EVENT_PHASE_MARK = 'R'; -export const TRACE_EVENT_PHASE_CLOCK_SYNC = 'c'; -export const TRACE_EVENT_PHASE_ENTER_CONTEXT = '('; -export const TRACE_EVENT_PHASE_LEAVE_CONTEXT = ')'; -export const TRACE_EVENT_PHASE_LINK_IDS = '='; -export const TRACE_EVENT_SCOPE_NAME_GLOBAL = 'g'; -export const TRACE_EVENT_SCOPE_NAME_PROCESS = 'p'; -export const TRACE_EVENT_SCOPE_NAME_THREAD = 't'; - -export const TRACE_EVENT_NAME = { - TRACING_STARTED_IN_PAGE: 'TracingStartedInPage', - PROFILE: 'Profile', - PROFILE_CHUNK: 'ProfileChunk', - CPU_PROFILE: 'CpuProfile', - V8_EXECUTE: 'V8.Execute', -}; - -export const PROCESS_NAME = { - BROWSER: 'Browser', - RENDERER: 'Renderer', - GPU: 'GPU Process', -}; - -export const TRACE_METADATA_NAME = { - PROCESS_NAME: 'process_name', - PROCESS_LABELS: 'process_labels', - PROCESS_SORT_INDEX: 'process_sort_index', - PROCESS_UPTIME_SECONDS: 'process_uptime_seconds', - THREAD_NAME: 'thread_name', - THREAD_SORT_INDEX: 'thread_sort_index', - NUM_CPUS: 'num_cpus', - TRACE_BUFFER_OVERFLOWED: 'trace_buffer_overflowed', -}; \ No newline at end of file diff --git a/src/tracerbench/trace/trace_event_comparator.js b/src/tracerbench/trace/trace_event_comparator.js deleted file mode 100644 index ea33b80b9bf71..0000000000000 --- a/src/tracerbench/trace/trace_event_comparator.js +++ /dev/null @@ -1,34 +0,0 @@ -import { TRACE_EVENT_PHASE_METADATA } from "./trace_event"; -export default function traceEventComparator(a, b) { - let res = 0; - if (a.ts !== b.ts) { - res = a.ts - b.ts; - } - else if (a.ph === TRACE_EVENT_PHASE_METADATA) { - res = -1; - } - else if (b.ph === TRACE_EVENT_PHASE_METADATA) { - res = 1; - } - if (res === 0) { - res = a.pid - b.pid; - if (res === 0) { - res = a.tid - b.tid; - if (res === 0) { - res = strcmp(a.ph, b.ph); - if (res === 0) { - res = strcmp(a.cat, b.cat); - if (res === 0) { - res = strcmp(a.name, b.name); - // TODO compare id, right now we only complete B/E - // if we do async events, this should compare ids too - } - } - } - } - } - return res; -} -function strcmp(a, b) { - return a < b ? -1 : a > b ? 1 : 0; -} diff --git a/src/types.js b/src/types.js index 66ebf68054868..f3444ba77bb71 100644 --- a/src/types.js +++ b/src/types.js @@ -1,6 +1,6 @@ // @flow -import type {Flamechart, FlamechartFrame} from './speedscope/lib/flamechart'; +import type {Flamechart, FlamechartFrame} from '@elg/speedscope'; // Type utilities diff --git a/src/util/__tests__/__snapshots__/preprocessData-test.js.snap b/src/util/__tests__/__snapshots__/preprocessData-test.js.snap index 0e0f5e3b87343..b3e12ceec7c9a 100644 --- a/src/util/__tests__/__snapshots__/preprocessData-test.js.snap +++ b/src/util/__tests__/__snapshots__/preprocessData-test.js.snap @@ -2,7 +2,7 @@ exports[`preprocessData should process complete set of events (page load sample data) 1`] = ` Object { - "duration": 2615.506, + "duration": 2586.895, "events": Array [ Object { "componentName": "Unknown", @@ -10,7 +10,7 @@ Object { "lanes": Array [ 9, ], - "timestamp": 307.43, + "timestamp": 278.073, "type": "schedule-render", }, Object { @@ -23,7 +23,7 @@ Object { at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) at App", "id": "0", - "timestamp": 687.702, + "timestamp": 658.345, "type": "suspense-suspend", }, Object { @@ -36,7 +36,7 @@ Object { at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) at App", "id": "1", - "timestamp": 690.096, + "timestamp": 660.739, "type": "suspense-suspend", }, Object { @@ -49,7 +49,7 @@ Object { at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) at App", "id": "2", - "timestamp": 691.911, + "timestamp": 662.554, "type": "suspense-suspend", }, Object { @@ -62,7 +62,7 @@ Object { at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) at App", "id": "3", - "timestamp": 692.812, + "timestamp": 663.455, "type": "suspense-suspend", }, Object { @@ -75,7 +75,7 @@ Object { at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) at App", "id": "4", - "timestamp": 693.559, + "timestamp": 664.202, "type": "suspense-suspend", }, Object { @@ -88,7 +88,7 @@ Object { at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) at App", "id": "0", - "timestamp": 696.037, + "timestamp": 666.68, "type": "suspense-suspend", }, Object { @@ -101,7 +101,7 @@ Object { at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) at App", "id": "1", - "timestamp": 696.558, + "timestamp": 667.201, "type": "suspense-suspend", }, Object { @@ -114,7 +114,7 @@ Object { at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) at App", "id": "2", - "timestamp": 697.097, + "timestamp": 667.74, "type": "suspense-suspend", }, Object { @@ -127,7 +127,7 @@ Object { at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) at App", "id": "3", - "timestamp": 697.639, + "timestamp": 668.282, "type": "suspense-suspend", }, Object { @@ -140,7 +140,7 @@ Object { at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) at App", "id": "4", - "timestamp": 698.205, + "timestamp": 668.848, "type": "suspense-suspend", }, Object { @@ -154,7 +154,7 @@ Object { at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) at App", "id": "0", - "timestamp": 700.692, + "timestamp": 671.335, "type": "suspense-suspend", }, Object { @@ -166,7 +166,7 @@ Object { "lanes": Array [ 0, ], - "timestamp": 708.795, + "timestamp": 679.438, "type": "schedule-state-update", }, Object { @@ -179,7 +179,7 @@ Object { at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) at App", "id": "1", - "timestamp": 1824.279, + "timestamp": 1794.922, "type": "suspense-resolved", }, Object { @@ -192,7 +192,7 @@ Object { at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) at App", "id": "1", - "timestamp": 1824.731, + "timestamp": 1795.374, "type": "suspense-resolved", }, Object { @@ -205,7 +205,7 @@ Object { at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) at App", "id": "0", - "timestamp": 1826.523, + "timestamp": 1797.166, "type": "suspense-suspend", }, Object { @@ -218,7 +218,7 @@ Object { at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) at App", "id": "2", - "timestamp": 1827.168, + "timestamp": 1797.811, "type": "suspense-suspend", }, Object { @@ -231,7 +231,7 @@ Object { at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) at App", "id": "3", - "timestamp": 1827.52, + "timestamp": 1798.163, "type": "suspense-suspend", }, Object { @@ -244,7 +244,7 @@ Object { at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) at App", "id": "4", - "timestamp": 1827.862, + "timestamp": 1798.505, "type": "suspense-suspend", }, Object { @@ -257,7 +257,7 @@ Object { at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) at App", "id": "2", - "timestamp": 1895.606, + "timestamp": 1866.249, "type": "suspense-resolved", }, Object { @@ -270,7 +270,7 @@ Object { at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) at App", "id": "2", - "timestamp": 1895.899, + "timestamp": 1866.542, "type": "suspense-resolved", }, Object { @@ -283,7 +283,7 @@ Object { at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) at App", "id": "2", - "timestamp": 1896.215, + "timestamp": 1866.858, "type": "suspense-resolved", }, Object { @@ -296,7 +296,7 @@ Object { at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) at App", "id": "0", - "timestamp": 1897.173, + "timestamp": 1867.816, "type": "suspense-suspend", }, Object { @@ -309,7 +309,7 @@ Object { at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) at App", "id": "3", - "timestamp": 1897.995, + "timestamp": 1868.638, "type": "suspense-suspend", }, Object { @@ -322,7 +322,7 @@ Object { at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) at App", "id": "4", - "timestamp": 1898.323, + "timestamp": 1868.966, "type": "suspense-suspend", }, Object { @@ -335,7 +335,7 @@ Object { at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) at App", "id": "3", - "timestamp": 2009.63, + "timestamp": 1980.273, "type": "suspense-resolved", }, Object { @@ -348,7 +348,7 @@ Object { at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) at App", "id": "3", - "timestamp": 2009.879, + "timestamp": 1980.522, "type": "suspense-resolved", }, Object { @@ -361,7 +361,7 @@ Object { at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) at App", "id": "3", - "timestamp": 2010.303, + "timestamp": 1980.946, "type": "suspense-resolved", }, Object { @@ -374,7 +374,7 @@ Object { at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) at App", "id": "3", - "timestamp": 2010.521, + "timestamp": 1981.164, "type": "suspense-resolved", }, Object { @@ -387,7 +387,7 @@ Object { at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) at App", "id": "0", - "timestamp": 2011.436, + "timestamp": 1982.079, "type": "suspense-suspend", }, Object { @@ -400,7 +400,7 @@ Object { at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) at App", "id": "4", - "timestamp": 2012.527, + "timestamp": 1983.17, "type": "suspense-suspend", }, Object { @@ -413,7 +413,7 @@ Object { at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) at App", "id": "4", - "timestamp": 2408.944, + "timestamp": 2379.587, "type": "suspense-resolved", }, Object { @@ -426,7 +426,7 @@ Object { at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) at App", "id": "4", - "timestamp": 2409.252, + "timestamp": 2379.895, "type": "suspense-resolved", }, Object { @@ -439,7 +439,7 @@ Object { at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) at App", "id": "4", - "timestamp": 2409.599, + "timestamp": 2380.242, "type": "suspense-resolved", }, Object { @@ -452,7 +452,7 @@ Object { at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) at App", "id": "4", - "timestamp": 2409.844, + "timestamp": 2380.487, "type": "suspense-resolved", }, Object { @@ -465,7 +465,7 @@ Object { at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) at App", "id": "4", - "timestamp": 2410.092, + "timestamp": 2380.735, "type": "suspense-resolved", }, Object { @@ -478,7 +478,7 @@ Object { at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) at App", "id": "0", - "timestamp": 2411.129, + "timestamp": 2381.772, "type": "suspense-suspend", }, Object { @@ -491,7 +491,7 @@ Object { at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) at App", "id": "0", - "timestamp": 2608.543, + "timestamp": 2579.186, "type": "suspense-resolved", }, Object { @@ -504,7 +504,7 @@ Object { at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) at App", "id": "0", - "timestamp": 2608.844, + "timestamp": 2579.487, "type": "suspense-resolved", }, Object { @@ -518,7 +518,7 @@ Object { at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) at App", "id": "0", - "timestamp": 2609.092, + "timestamp": 2579.735, "type": "suspense-resolved", }, Object { @@ -531,7 +531,7 @@ Object { at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) at App", "id": "0", - "timestamp": 2609.399, + "timestamp": 2580.042, "type": "suspense-resolved", }, Object { @@ -544,7 +544,7 @@ Object { at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) at App", "id": "0", - "timestamp": 2609.647, + "timestamp": 2580.29, "type": "suspense-resolved", }, Object { @@ -557,7 +557,7 @@ Object { at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) at App", "id": "0", - "timestamp": 2609.903, + "timestamp": 2580.546, "type": "suspense-resolved", }, Object { @@ -570,7 +570,7 @@ Object { at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) at App", "id": "0", - "timestamp": 2610.157, + "timestamp": 2580.8, "type": "suspense-resolved", }, ], @@ -582,7 +582,7 @@ Object { "lanes": Array [ 9, ], - "timestamp": 314.65, + "timestamp": 285.293, "type": "render-idle", }, Object { @@ -592,87 +592,87 @@ Object { "lanes": Array [ 9, ], - "timestamp": 314.65, + "timestamp": 285.293, "type": "render", }, Object { "batchUID": 0, "depth": 0, - "duration": 8.168000000000006, + "duration": 8.16799999999995, "lanes": Array [ 9, ], - "timestamp": 327.065, + "timestamp": 297.708, "type": "render", }, Object { "batchUID": 0, "depth": 0, - "duration": 4.988999999999976, + "duration": 4.989000000000033, "lanes": Array [ 9, ], - "timestamp": 339.814, + "timestamp": 310.457, "type": "render", }, Object { "batchUID": 0, "depth": 0, - "duration": 6.46999999999997, + "duration": 6.470000000000027, "lanes": Array [ 9, ], - "timestamp": 387.124, + "timestamp": 357.767, "type": "render", }, Object { "batchUID": 0, "depth": 0, - "duration": 6.632999999999981, + "duration": 6.633000000000038, "lanes": Array [ 9, ], - "timestamp": 400.843, + "timestamp": 371.486, "type": "render", }, Object { "batchUID": 0, "depth": 0, - "duration": 9.890000000000043, + "duration": 9.889999999999986, "lanes": Array [ 9, ], - "timestamp": 414.407, + "timestamp": 385.05, "type": "render", }, Object { "batchUID": 0, "depth": 0, - "duration": 7.859000000000037, + "duration": 7.8589999999999804, "lanes": Array [ 9, ], - "timestamp": 427.417, + "timestamp": 398.06, "type": "render", }, Object { "batchUID": 0, "depth": 0, - "duration": 7.260999999999967, + "duration": 7.261000000000024, "lanes": Array [ 9, ], - "timestamp": 436.023, + "timestamp": 406.666, "type": "render", }, Object { "batchUID": 0, "depth": 0, - "duration": 7.701000000000022, + "duration": 7.700999999999965, "lanes": Array [ 9, ], - "timestamp": 443.575, + "timestamp": 414.218, "type": "render", }, Object { @@ -682,17 +682,17 @@ Object { "lanes": Array [ 9, ], - "timestamp": 451.498, + "timestamp": 422.141, "type": "render", }, Object { "batchUID": 0, "depth": 0, - "duration": 7.7070000000000505, + "duration": 7.706999999999994, "lanes": Array [ 9, ], - "timestamp": 459.542, + "timestamp": 430.185, "type": "render", }, Object { @@ -702,7 +702,7 @@ Object { "lanes": Array [ 9, ], - "timestamp": 468.909, + "timestamp": 439.552, "type": "render", }, Object { @@ -712,67 +712,67 @@ Object { "lanes": Array [ 9, ], - "timestamp": 476.651, + "timestamp": 447.294, "type": "render", }, Object { "batchUID": 0, "depth": 0, - "duration": 7.73599999999999, + "duration": 7.736000000000047, "lanes": Array [ 9, ], - "timestamp": 484.572, + "timestamp": 455.215, "type": "render", }, Object { "batchUID": 0, "depth": 0, - "duration": 7.696000000000026, + "duration": 7.6959999999999695, "lanes": Array [ 9, ], - "timestamp": 492.616, + "timestamp": 463.259, "type": "render", }, Object { "batchUID": 0, "depth": 0, - "duration": 7.701000000000022, + "duration": 7.700999999999965, "lanes": Array [ 9, ], - "timestamp": 500.604, + "timestamp": 471.247, "type": "render", }, Object { "batchUID": 0, "depth": 0, - "duration": 7.555000000000007, + "duration": 7.55499999999995, "lanes": Array [ 9, ], - "timestamp": 508.719, + "timestamp": 479.362, "type": "render", }, Object { "batchUID": 0, "depth": 0, - "duration": 7.789999999999964, + "duration": 7.7900000000000205, "lanes": Array [ 9, ], - "timestamp": 516.552, + "timestamp": 487.195, "type": "render", }, Object { "batchUID": 0, "depth": 0, - "duration": 7.616999999999962, + "duration": 7.617000000000019, "lanes": Array [ 9, ], - "timestamp": 524.711, + "timestamp": 495.354, "type": "render", }, Object { @@ -782,17 +782,17 @@ Object { "lanes": Array [ 9, ], - "timestamp": 533.063, + "timestamp": 503.706, "type": "render", }, Object { "batchUID": 0, "depth": 0, - "duration": 7.819000000000074, + "duration": 7.81899999999996, "lanes": Array [ 9, ], - "timestamp": 542.463, + "timestamp": 513.106, "type": "render", }, Object { @@ -802,37 +802,37 @@ Object { "lanes": Array [ 9, ], - "timestamp": 551.024, + "timestamp": 521.667, "type": "render", }, Object { "batchUID": 0, "depth": 0, - "duration": 7.7579999999999245, + "duration": 7.758000000000038, "lanes": Array [ 9, ], - "timestamp": 560.542, + "timestamp": 531.185, "type": "render", }, Object { "batchUID": 0, "depth": 0, - "duration": 7.7349999999999, + "duration": 7.735000000000014, "lanes": Array [ 9, ], - "timestamp": 568.57, + "timestamp": 539.213, "type": "render", }, Object { "batchUID": 0, "depth": 0, - "duration": 7.7299999999999045, + "duration": 7.730000000000018, "lanes": Array [ 9, ], - "timestamp": 576.58, + "timestamp": 547.223, "type": "render", }, Object { @@ -842,77 +842,77 @@ Object { "lanes": Array [ 9, ], - "timestamp": 584.591, + "timestamp": 555.234, "type": "render", }, Object { "batchUID": 0, "depth": 0, - "duration": 7.714999999999918, + "duration": 7.715000000000032, "lanes": Array [ 9, ], - "timestamp": 592.589, + "timestamp": 563.232, "type": "render", }, Object { "batchUID": 0, "depth": 0, - "duration": 7.761000000000081, + "duration": 7.760999999999967, "lanes": Array [ 9, ], - "timestamp": 600.569, + "timestamp": 571.212, "type": "render", }, Object { "batchUID": 0, "depth": 0, - "duration": 7.617999999999938, + "duration": 7.618000000000052, "lanes": Array [ 9, ], - "timestamp": 608.681, + "timestamp": 579.324, "type": "render", }, Object { "batchUID": 0, "depth": 0, - "duration": 7.738000000000056, + "duration": 7.737999999999943, "lanes": Array [ 9, ], - "timestamp": 616.558, + "timestamp": 587.201, "type": "render", }, Object { "batchUID": 0, "depth": 0, - "duration": 7.738999999999919, + "duration": 7.739000000000033, "lanes": Array [ 9, ], - "timestamp": 624.566, + "timestamp": 595.209, "type": "render", }, Object { "batchUID": 0, "depth": 0, - "duration": 7.731999999999971, + "duration": 7.732000000000085, "lanes": Array [ 9, ], - "timestamp": 632.551, + "timestamp": 603.194, "type": "render", }, Object { "batchUID": 0, "depth": 0, - "duration": 7.713000000000079, + "duration": 7.712999999999965, "lanes": Array [ 9, ], - "timestamp": 640.569, + "timestamp": 611.212, "type": "render", }, Object { @@ -922,7 +922,7 @@ Object { "lanes": Array [ 9, ], - "timestamp": 648.931, + "timestamp": 619.574, "type": "render", }, Object { @@ -932,7 +932,7 @@ Object { "lanes": Array [ 9, ], - "timestamp": 656.545, + "timestamp": 627.188, "type": "render", }, Object { @@ -942,7 +942,7 @@ Object { "lanes": Array [ 9, ], - "timestamp": 664.55, + "timestamp": 635.193, "type": "render", }, Object { @@ -952,7 +952,7 @@ Object { "lanes": Array [ 9, ], - "timestamp": 672.563, + "timestamp": 643.206, "type": "render", }, Object { @@ -962,7 +962,7 @@ Object { "lanes": Array [ 9, ], - "timestamp": 680.696, + "timestamp": 651.339, "type": "render", }, Object { @@ -972,7 +972,7 @@ Object { "lanes": Array [ 9, ], - "timestamp": 688.802, + "timestamp": 659.445, "type": "render", }, Object { @@ -982,7 +982,7 @@ Object { "lanes": Array [ 9, ], - "timestamp": 694.309, + "timestamp": 664.952, "type": "render", }, Object { @@ -992,37 +992,37 @@ Object { "lanes": Array [ 9, ], - "timestamp": 700.141, + "timestamp": 670.784, "type": "render", }, Object { "batchUID": 0, "depth": 0, - "duration": 14.551999999999907, + "duration": 14.552000000000021, "lanes": Array [ 9, ], - "timestamp": 702.681, + "timestamp": 673.324, "type": "commit", }, Object { "batchUID": 0, "depth": 1, - "duration": 2.689000000000078, + "duration": 2.6889999999999645, "lanes": Array [ 9, ], - "timestamp": 706.593, + "timestamp": 677.236, "type": "layout-effects", }, Object { "batchUID": 1, "depth": 1, - "duration": 3.55600000000004, + "duration": 3.5559999999999263, "lanes": Array [ 0, ], - "timestamp": 713.461, + "timestamp": 684.104, "type": "render-idle", }, Object { @@ -1032,7 +1032,7 @@ Object { "lanes": Array [ 0, ], - "timestamp": 713.461, + "timestamp": 684.104, "type": "render", }, Object { @@ -1042,7 +1042,7 @@ Object { "lanes": Array [ 0, ], - "timestamp": 715.705, + "timestamp": 686.348, "type": "commit", }, Object { @@ -1052,7 +1052,7 @@ Object { "lanes": Array [ 0, ], - "timestamp": 716.624, + "timestamp": 687.267, "type": "layout-effects", }, Object { @@ -1062,27 +1062,27 @@ Object { "lanes": Array [ 10, ], - "timestamp": 1825.399, + "timestamp": 1796.042, "type": "render-idle", }, Object { "batchUID": 2, "depth": 0, - "duration": 3.43300000000022, + "duration": 3.4329999999999927, "lanes": Array [ 10, ], - "timestamp": 1825.399, + "timestamp": 1796.042, "type": "render", }, Object { "batchUID": 2, "depth": 0, - "duration": 2.588999999999942, + "duration": 2.589000000000169, "lanes": Array [ 10, ], - "timestamp": 1828.929, + "timestamp": 1799.572, "type": "commit", }, Object { @@ -1092,7 +1092,7 @@ Object { "lanes": Array [ 10, ], - "timestamp": 1830.962, + "timestamp": 1801.605, "type": "layout-effects", }, Object { @@ -1102,7 +1102,7 @@ Object { "lanes": Array [ 11, ], - "timestamp": 1896.355, + "timestamp": 1866.998, "type": "render-idle", }, Object { @@ -1112,7 +1112,7 @@ Object { "lanes": Array [ 11, ], - "timestamp": 1896.355, + "timestamp": 1866.998, "type": "render", }, Object { @@ -1122,27 +1122,27 @@ Object { "lanes": Array [ 11, ], - "timestamp": 1899.052, + "timestamp": 1869.695, "type": "commit", }, Object { "batchUID": 3, "depth": 1, - "duration": 0.01999999999998181, + "duration": 0.020000000000209184, "lanes": Array [ 11, ], - "timestamp": 1900.121, + "timestamp": 1870.764, "type": "layout-effects", }, Object { "batchUID": 4, "depth": 0, - "duration": 3.768000000000029, + "duration": 3.7679999999998017, "lanes": Array [ 12, ], - "timestamp": 2010.718, + "timestamp": 1981.361, "type": "render-idle", }, Object { @@ -1152,17 +1152,17 @@ Object { "lanes": Array [ 12, ], - "timestamp": 2010.718, + "timestamp": 1981.361, "type": "render", }, Object { "batchUID": 4, "depth": 0, - "duration": 1.2580000000000382, + "duration": 1.2579999999998108, "lanes": Array [ 12, ], - "timestamp": 2013.228, + "timestamp": 1983.871, "type": "commit", }, Object { @@ -1172,7 +1172,7 @@ Object { "lanes": Array [ 12, ], - "timestamp": 2014.288, + "timestamp": 1984.931, "type": "layout-effects", }, Object { @@ -1182,7 +1182,7 @@ Object { "lanes": Array [ 13, ], - "timestamp": 2410.326, + "timestamp": 2380.969, "type": "render-idle", }, Object { @@ -1192,7 +1192,7 @@ Object { "lanes": Array [ 13, ], - "timestamp": 2410.326, + "timestamp": 2380.969, "type": "render", }, Object { @@ -1202,7 +1202,7 @@ Object { "lanes": Array [ 13, ], - "timestamp": 2412.695, + "timestamp": 2383.338, "type": "commit", }, Object { @@ -1212,7 +1212,7 @@ Object { "lanes": Array [ 13, ], - "timestamp": 2413.892, + "timestamp": 2384.535, "type": "layout-effects", }, Object { @@ -1222,7 +1222,7 @@ Object { "lanes": Array [ 14, ], - "timestamp": 2610.309, + "timestamp": 2580.952, "type": "render-idle", }, Object { @@ -1232,7 +1232,7 @@ Object { "lanes": Array [ 14, ], - "timestamp": 2610.309, + "timestamp": 2580.952, "type": "render", }, Object { @@ -1242,7 +1242,7 @@ Object { "lanes": Array [ 14, ], - "timestamp": 2613.805, + "timestamp": 2584.448, "type": "commit", }, Object { @@ -1252,17 +1252,17 @@ Object { "lanes": Array [ 14, ], - "timestamp": 2615.479, + "timestamp": 2586.122, "type": "layout-effects", }, ], - "startTime": 8993749139, + "startTime": 8993778496, } `; exports[`preprocessData should process forced update event 1`] = ` Object { - "duration": 3.988, + "duration": 67.461, "events": Array [ Object { "componentName": "ForceUpdateDemo_ForceUpdateDemo", @@ -1273,7 +1273,7 @@ Object { "lanes": Array [ 4, ], - "timestamp": 0, + "timestamp": 63.355, "type": "schedule-force-update", }, ], @@ -1281,44 +1281,44 @@ Object { Object { "batchUID": 0, "depth": 0, - "duration": 2.191, + "duration": 2.1910000000000025, "lanes": Array [ 4, ], - "timestamp": 1.915, + "timestamp": 65.27, "type": "render-idle", }, Object { "batchUID": 0, "depth": 0, - "duration": 0.9769999999999999, + "duration": 0.9770000000000039, "lanes": Array [ 4, ], - "timestamp": 1.915, + "timestamp": 65.27, "type": "render", }, Object { "batchUID": 0, "depth": 0, - "duration": 1.1669999999999998, + "duration": 1.1670000000000016, "lanes": Array [ 4, ], - "timestamp": 2.939, + "timestamp": 66.294, "type": "commit", }, Object { "batchUID": 0, "depth": 1, - "duration": 0.017999999999999794, + "duration": 0.018000000000000682, "lanes": Array [ 4, ], - "timestamp": 3.97, + "timestamp": 67.325, "type": "layout-effects", }, ], - "startTime": 40806988231, + "startTime": 40806924876, } `; diff --git a/src/util/__tests__/preprocessData-test.js b/src/util/__tests__/preprocessData-test.js index d77c8d3b3dc00..4ee5e78dfffc1 100644 --- a/src/util/__tests__/preprocessData-test.js +++ b/src/util/__tests__/preprocessData-test.js @@ -59,10 +59,25 @@ describe(preprocessData, () => { }); }); + it('should return empty data given a timeline with no Profile event', () => { + expect( + // prettier-ignore + preprocessData([ + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--schedule-render-Unknown-512-","ph":"R","pid":9312,"tid":10252,"ts":8994056569,"tts":1816966}, + ]), + ).toEqual({ + startTime: 0, + duration: 0, + events: [], + measures: [], + }); + }); + it('should return empty data given a timeline with no React scheduling profiling marks', () => { expect( // prettier-ignore preprocessData([ + {"args":{"data":{"startTime":8993778496}},"cat":"disabled-by-default-v8.cpu_profiler","id":"0x1","name":"Profile","ph":"P","pid":9312,"tid":10252,"ts":8993778520,"tts":1614266}, {"pid":57632,"tid":38659,"ts":874860756135,"ph":"X","cat":"disabled-by-default-devtools.timeline","name":"RunTask","dur":18,"tdur":19,"tts":8700284918,"args":{}}, {"pid":57632,"tid":38659,"ts":874860756158,"ph":"X","cat":"disabled-by-default-devtools.timeline","name":"RunTask","dur":30,"tdur":30,"tts":8700284941,"args":{}}, {"pid":57632,"tid":38659,"ts":874860756192,"ph":"X","cat":"disabled-by-default-devtools.timeline","name":"RunTask","dur":21,"tdur":20,"tts":8700284976,"args":{}}, @@ -71,8 +86,8 @@ describe(preprocessData, () => { {"pid":57632,"tid":38659,"ts":874860756233,"ph":"X","cat":"disabled-by-default-devtools.timeline","name":"RunTask","dur":5,"tdur":4,"tts":8700285017,"args":{}}, ]), ).toEqual({ - startTime: 874860756135, - duration: 0, + startTime: 8993778496, + duration: 865866977.737, events: [], measures: [], }); @@ -80,8 +95,9 @@ describe(preprocessData, () => { it('should throw if unrecognized React mark is encountered', () => { expect(() => + // prettier-ignore preprocessData([ - // prettier-ignore + {"args":{"data":{"startTime":8993778496}},"cat":"disabled-by-default-v8.cpu_profiler","id":"0x1","name":"Profile","ph":"P","pid":9312,"tid":10252,"ts":8993778520,"tts":1614266}, {"args":{"data":{"navigationId":"E082C30FBDA3ACEE0E7B5FD75F8B7F0D"}},"cat":"blink.user_timing","name":"--there-are-four-lights","ph":"R","pid":17232,"tid":13628,"ts":264686513020,"tts":4082554}, ]), ).toThrow(); @@ -89,8 +105,9 @@ describe(preprocessData, () => { it('should throw if events and measures are incomplete', () => { const error = jest.spyOn(console, 'error'); + // prettier-ignore preprocessData([ - // prettier-ignore + {"args":{"data":{"startTime":8993778496}},"cat":"disabled-by-default-v8.cpu_profiler","id":"0x1","name":"Profile","ph":"P","pid":9312,"tid":10252,"ts":8993778520,"tts":1614266}, {"args":{"data":{"navigationId":"1065756F5FDAD64BE45CA86B0BBC1F8B"}},"cat":"blink.user_timing","name":"--render-start-8","ph":"R","pid":1852,"tid":12484,"ts":42351664678,"tts":1512475}, ]); expect(error).toHaveBeenCalled(); @@ -98,8 +115,9 @@ describe(preprocessData, () => { it('should throw if work is completed without being started', () => { const error = jest.spyOn(console, 'error'); + // prettier-ignore preprocessData([ - // prettier-ignore + {"args":{"data":{"startTime":8993778496}},"cat":"disabled-by-default-v8.cpu_profiler","id":"0x1","name":"Profile","ph":"P","pid":9312,"tid":10252,"ts":8993778520,"tts":1614266}, {"args":{"data":{"navigationId":"E082C30FBDA3ACEE0E7B5FD75F8B7F0D"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":17232,"tid":13628,"ts":264686513020,"tts":4082554}, ]); expect(error).toHaveBeenCalled(); @@ -112,6 +130,7 @@ describe(preprocessData, () => { // prettier-ignore preprocessData([ {"args":{"data":{"documentLoaderURL":"https://concurrent-demo.now.sh/","isLoadingMainFrame":true,"navigationId":"43BC238A4FB7548146D3CD739C9C9434"},"frame":"FD65D9AFD04B1295CEA36B883F0FA82F"},"cat":"blink.user_timing","name":"navigationStart","ph":"R","pid":9312,"tid":10252,"ts":8993749139,"tts":1646191}, + {"args":{"data":{"startTime":8993778496}},"cat":"disabled-by-default-v8.cpu_profiler","id":"0x1","name":"Profile","ph":"P","pid":9312,"tid":10252,"ts":8993778520,"tts":1614266}, {"args":{"frame":"FD65D9AFD04B1295CEA36B883F0FA82F"},"cat":"blink.user_timing","name":"fetchStart","ph":"R","pid":9312,"tid":10252,"ts":8993751576,"tts":1646197}, {"args":{},"cat":"blink.user_timing","name":"requestStart","ph":"R","pid":9312,"tid":10252,"ts":8993757325,"tts":1612760}, {"args":{"frame":"FD65D9AFD04B1295CEA36B883F0FA82F"},"cat":"blink.user_timing","name":"responseEnd","ph":"R","pid":9312,"tid":10252,"ts":8993762841,"tts":1652151}, @@ -303,6 +322,7 @@ describe(preprocessData, () => { expect( // prettier-ignore preprocessData([ + {"args":{"data":{"startTime":40806924876}},"cat":"disabled-by-default-v8.cpu_profiler","id":"0x2","name":"Profile","ph":"P","pid":1852,"tid":12484,"ts":40806924880,"tts":996658}, {"args":{"data":{"navigationId":"1065756F5FDAD64BE45CA86B0BBC1F8B"}},"cat":"blink.user_timing","name":"--schedule-forced-update-ForceUpdateDemo_ForceUpdateDemo-16-\n at ForceUpdateDemo_ForceUpdateDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:18:98)\n at App","ph":"R","pid":1852,"tid":12484,"ts":40806988231,"tts":1037762}, {"args":{"data":{"navigationId":"1065756F5FDAD64BE45CA86B0BBC1F8B"}},"cat":"blink.user_timing","name":"--render-start-16","ph":"R","pid":1852,"tid":12484,"ts":40806990146,"tts":1038890}, {"args":{"data":{"navigationId":"1065756F5FDAD64BE45CA86B0BBC1F8B"}},"cat":"blink.user_timing","name":"--render-stop","ph":"R","pid":1852,"tid":12484,"ts":40806991123,"tts":1039401}, diff --git a/src/util/preprocessData.js b/src/util/preprocessData.js index 8994989e807f4..4a3bc8aff7aea 100644 --- a/src/util/preprocessData.js +++ b/src/util/preprocessData.js @@ -1,6 +1,6 @@ // @flow -import type {TimelineEvent} from '../speedscope/import/chrome'; +import type {TimelineEvent} from '@elg/speedscope'; import type { Milliseconds, BatchUID, @@ -361,19 +361,27 @@ export default function preprocessData( // TODO: Sort `timeline`. JSON Array Format trace events need not be ordered. See: // https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview#heading=h.f2f0yd51wi15 - const indexOfFirstEventWithTs = timeline.findIndex(event => !!event.ts); - - // Our user timing events are Complete Events (i.e. ph === 'X') and will - // always have ts. If there are no ts events, we can safely abort, knowing - // that there are no events to process. - // See: https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview#heading=h.lpfof2aylapb - if (indexOfFirstEventWithTs === -1) { + // Events displayed in flamechart have timestamps relative to the profile + // event's startTime. Source: https://github.com/v8/v8/blob/44bd8fd7/src/inspector/js_protocol.json#L1486 + // + // We'll thus expect there to be a 'Profile' event; if there is not one, we + // can deduce that there are no flame chart events. As we expect React + // scheduling profiling user timing marks to be recorded together with browser + // flame chart events, we can futher deduce that the data is invalid and we + // don't bother finding React events. + const indexOfProfileEvent = timeline.findIndex( + event => event.name === 'Profile', + ); + if (indexOfProfileEvent === -1) { return profilerData; } - // `profilerData.startTime` cannot be 0 or undefined, otherwise the final - // computed React measures will have enormous `timestamp` values. - profilerData.startTime = timeline[indexOfFirstEventWithTs].ts; + // Use Profile event's `startTime` as the start time to align with flame chart. + // TODO: Remove assumption that there'll only be 1 'Profile' event. If this + // assumption does not hold, the chart may start at the wrong time. + profilerData.startTime = timeline[indexOfProfileEvent].args.data.startTime; + profilerData.duration = + (timeline[timeline.length - 1].ts - profilerData.startTime) / 1000; const state: ProcessorState = { batchUID: 0, @@ -390,19 +398,5 @@ export default function preprocessData( console.error(`Incomplete events or measures`, measureStack); } - // Compute profilerData.duration - const {events, measures} = profilerData; - if (events.length > 0) { - const {timestamp} = events[events.length - 1]; - profilerData.duration = Math.max(profilerData.duration, timestamp); - } - if (measures.length > 0) { - const {duration, timestamp} = measures[measures.length - 1]; - profilerData.duration = Math.max( - profilerData.duration, - timestamp + duration, - ); - } - return profilerData; } diff --git a/src/util/preprocessFlamechart.js b/src/util/preprocessFlamechart.js index 6774f85c3567a..dc99185115896 100644 --- a/src/util/preprocessFlamechart.js +++ b/src/util/preprocessFlamechart.js @@ -1,10 +1,9 @@ // @flow -import {importFromChromeTimeline} from '../speedscope/import/chrome'; -import {Flamechart} from '../speedscope/lib/flamechart'; +import {importFromChromeTimeline, Flamechart} from '@elg/speedscope'; -import type {TimelineEvent} from './speedscope/import/chrome'; -import type {FlamechartData} from './types'; +import type {TimelineEvent} from '@elg/speedscope'; +import type {FlamechartData} from '../types'; export default function preprocessFlamechart( rawData: TimelineEvent[], diff --git a/yarn.lock b/yarn.lock index 6b2ce5ffdb702..ee04901452eef 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1730,6 +1730,14 @@ exec-sh "^0.3.2" minimist "^1.2.0" +"@elg/speedscope@1.6.0-787837d": + version "1.6.0-787837d" + resolved "https://registry.yarnpkg.com/@elg/speedscope/-/speedscope-1.6.0-787837d.tgz#2b9bcd8a5d5e7eb53e3db838456eb2e745def1bf" + integrity sha512-LrPUHP9C06eLcXkKXg0PrkRIteYe75IUxJ21dBpUohWoEMMa4ET056Ycj/zj/ChxcCemHnorloH/jSS2db8M1A== + dependencies: + opn "5.3.0" + react "^16.13.1" + "@iarna/toml@^2.2.0": version "2.2.3" resolved "https://registry.yarnpkg.com/@iarna/toml/-/toml-2.2.3.tgz#f060bf6eaafae4d56a7dac618980838b0696e2ab" @@ -5939,6 +5947,11 @@ is-windows@^1.0.2: resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== +is-wsl@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" + integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= + is-wsl@^2.1.1: version "2.2.0" resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" @@ -7281,6 +7294,13 @@ onetime@^5.1.0: dependencies: mimic-fn "^2.1.0" +opn@5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/opn/-/opn-5.3.0.tgz#64871565c863875f052cfdf53d3e3cb5adb53b1c" + integrity sha512-bYJHo/LOmoTd+pfiYhfZDnf9zekVJrY+cnS2a5F2x+w5ppvTqObojTP7WiFG+kVZs9Inw+qQ/lw7TroWwhdd2g== + dependencies: + is-wsl "^1.1.0" + optionator@^0.8.1: version "0.8.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" From a74031bd4e4be3bef68fd72f4c6a2fff2439257d Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Wed, 8 Jul 2020 14:46:24 +0800 Subject: [PATCH 037/116] Add minor EventTooltip improvements --- src/EventTooltip.js | 43 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/src/EventTooltip.js b/src/EventTooltip.js index 23487d1685483..3994a9fdbbf99 100644 --- a/src/EventTooltip.js +++ b/src/EventTooltip.js @@ -23,6 +23,14 @@ type Props = {| state: PanAndZoomState, |}; +function formatTimestamp(ms) { + return ms.toLocaleString(undefined, {minimumFractionDigits: 2}) + 'ms'; +} + +function formatDuration(ms) { + return prettyMilliseconds(ms, {millisecondsDecimalDigits: 3}); +} + export default function EventTooltip({data, hoveredEvent, state}: Props) { const {canvasMouseY, canvasMouseX} = state; @@ -132,11 +140,24 @@ const TooltipFlamechartNode = ({ color: COLORS.TOOLTIP, }} ref={tooltipRef}> - {prettyMilliseconds((end - start) / 1000)} {name} + {formatDuration((end - start) / 1000)} {name}
-
Script URL:
{file} -
Location:
- line {line}, column {col} +
Timestamp:
+
{formatTimestamp(start / 1000)}
+ {file && ( + <> +
Script URL:
+
{file}
+ + )} + {(line !== undefined || col !== undefined) && ( + <> +
Location:
+
+ line {line}, column {col} +
+ + )}
); @@ -194,7 +215,7 @@ const TooltipReactEvent = ({
Timestamp:
- {prettyMilliseconds(timestamp)} +
{formatTimestamp(timestamp)}
{componentStack && (
Component stack:
@@ -217,7 +238,7 @@ const TooltipReactMeasure = ({ measure: ReactMeasure, tooltipRef: Return, }) => { - const {batchUID, duration, timestamp, type} = measure; + const {batchUID, duration, timestamp, type, lanes} = measure; let label = null; switch (type) { @@ -251,13 +272,17 @@ const TooltipReactMeasure = ({ color: COLORS.TOOLTIP, }} ref={tooltipRef}> - {prettyMilliseconds(duration)} {label} + {formatDuration(duration)} {label}
Timestamp:
- {prettyMilliseconds(timestamp)} +
{formatTimestamp(timestamp)}
Batch duration:
- {prettyMilliseconds(stopTime - startTime)} +
{formatDuration(stopTime - startTime)}
+
+ Lane{lanes.length === 1 ? '' : 's'}: +
+
{lanes.join(', ')}
); From ce2f36188530393ca7c0697f3527cb8d8fdb632c Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Wed, 8 Jul 2020 15:58:59 +0800 Subject: [PATCH 038/116] Upgrade Parcel and Flow and fix Flow config (#58) * Upgrade Parcel to latest beta * Fix Flow ignore regexes and ignore more paths * Remove profile-filtered.* files 1. They are not valid JSON 2. We don't need them anymore * Upgrade Flow --- .flowconfig | 5 +- .parcelrc | 8 +- package.json | 10 +- yarn.lock | 3069 +++++++++++++++++++++++++++++--------------------- 4 files changed, 1779 insertions(+), 1313 deletions(-) diff --git a/.flowconfig b/.flowconfig index 042c3ca7f8d4b..3e03152eed269 100644 --- a/.flowconfig +++ b/.flowconfig @@ -1,5 +1,8 @@ [ignore] -./src/graveyard +/src/graveyard/.* +/.parcel-cache/.* +/coverage/.* +/static/.*\.json [include] diff --git a/.parcelrc b/.parcelrc index 05f13a17c95e9..21ccbbc1af44b 100644 --- a/.parcelrc +++ b/.parcelrc @@ -1,6 +1,8 @@ { "extends": "@parcel/config-default", - "transforms": { - "url:*": ["@parcel/transformer-raw"] + "transformers": { + "*.{json,json5}": [ + "@parcel/transformer-raw" + ] } -} \ No newline at end of file +} diff --git a/package.json b/package.json index a572f9215eef2..7467478fef91a 100644 --- a/package.json +++ b/package.json @@ -2,9 +2,9 @@ "name": "scheduling-profiler-prototype", "version": "0.0.1", "scripts": { - "build": "parcel build index.html --no-cache", + "build": "parcel build --no-cache index.html", "prettier": "prettier --write \"**/*.{js,json,css}\"", - "start": "parcel index.html --no-cache", + "start": "parcel index.html", "lint": "eslint \"src/**/*.js\"", "test": "jest" }, @@ -24,7 +24,7 @@ "scheduler": "^0.19.1" }, "devDependencies": { - "@babel/core": "^7.10.3", + "@babel/core": "^7.10.4", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.3.0", "babel-eslint": "^10.1.0", @@ -39,10 +39,10 @@ "eslint-plugin-jest": "^23.17.1", "eslint-plugin-no-for-of-loops": "^1.0.1", "eslint-plugin-react": "^7.20.0", - "flow-bin": "^0.127.0", + "flow-bin": "^0.128.0", "identity-obj-proxy": "^3.0.0", "jest": "^26.0.1", - "parcel": "2.0.0-alpha.3.2", + "parcel": "2.0.0-beta.1", "postcss-modules": "^2.0.0", "prettier": "1.19.1" } diff --git a/yarn.lock b/yarn.lock index ee04901452eef..650b64ba7697d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -16,6 +16,13 @@ dependencies: "@babel/highlight" "^7.10.3" +"@babel/code-frame@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a" + integrity sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg== + dependencies: + "@babel/highlight" "^7.10.4" + "@babel/compat-data@^7.10.1", "@babel/compat-data@^7.9.0": version "7.10.3" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.10.3.tgz#9af3e033f36e8e2d6e47570db91e64a846f5d382" @@ -25,6 +32,15 @@ invariant "^2.2.4" semver "^5.5.0" +"@babel/compat-data@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.10.4.tgz#706a6484ee6f910b719b696a9194f8da7d7ac241" + integrity sha512-t+rjExOrSVvjQQXNp5zAIYDp00KjdvGl/TpDX5REPr0S9IAIPQMTilcfG6q8c0QFmj9lSTVySV2VTsyggvtNIw== + dependencies: + browserslist "^4.12.0" + invariant "^2.2.4" + semver "^5.5.0" + "@babel/core@7.9.0": version "7.9.0" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.9.0.tgz#ac977b538b77e132ff706f3b8a4dbad09c03c56e" @@ -67,7 +83,7 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/core@^7.1.0", "@babel/core@^7.10.3", "@babel/core@^7.7.5": +"@babel/core@^7.1.0", "@babel/core@^7.7.5": version "7.10.3" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.10.3.tgz#73b0e8ddeec1e3fdd7a2de587a60e17c440ec77e" integrity sha512-5YqWxYE3pyhIi84L84YcwjeEgS+fa7ZjK6IBVGTjDVfm64njkR2lfDhVR5OudLk8x2GK59YoSyVv+L/03k1q9w== @@ -89,6 +105,28 @@ semver "^5.4.1" source-map "^0.5.0" +"@babel/core@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.10.4.tgz#780e8b83e496152f8dd7df63892b2e052bf1d51d" + integrity sha512-3A0tS0HWpy4XujGc7QtOIHTeNwUgWaZc/WuS5YQrfhU67jnVmsD6OGPc1AKHH0LJHQICGncy3+YUjIhVlfDdcA== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.10.4" + "@babel/helper-module-transforms" "^7.10.4" + "@babel/helpers" "^7.10.4" + "@babel/parser" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.1" + json5 "^2.1.2" + lodash "^4.17.13" + resolve "^1.3.2" + semver "^5.4.1" + source-map "^0.5.0" + "@babel/generator@^7.0.0", "@babel/generator@^7.3.3", "@babel/generator@^7.7.4", "@babel/generator@^7.7.7": version "7.7.7" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.7.7.tgz#859ac733c44c74148e1a72980a64ec84b85f4f45" @@ -109,6 +147,16 @@ lodash "^4.17.13" source-map "^0.5.0" +"@babel/generator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.10.4.tgz#e49eeed9fe114b62fa5b181856a43a5e32f5f243" + integrity sha512-toLIHUIAgcQygFZRAQcsLQV3CBuX6yOIru1kJk/qqqvcRmZrYe6WavZTSG+bB8MxhnL9YPf+pKQfuiP161q7ng== + dependencies: + "@babel/types" "^7.10.4" + jsesc "^2.5.1" + lodash "^4.17.13" + source-map "^0.5.0" + "@babel/helper-annotate-as-pure@^7.10.1": version "7.10.1" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.1.tgz#f6d08acc6f70bbd59b436262553fb2e259a1a268" @@ -116,6 +164,13 @@ dependencies: "@babel/types" "^7.10.1" +"@babel/helper-annotate-as-pure@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz#5bf0d495a3f757ac3bda48b5bf3b3ba309c72ba3" + integrity sha512-XQlqKQP4vXFB7BN8fEEerrmYvHp3fK/rBkRFz9jaJbzK0B1DSfej9Kc7ZzE8Z/OnId1jpJdNAZ3BFQjWG68rcA== + dependencies: + "@babel/types" "^7.10.4" + "@babel/helper-annotate-as-pure@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.7.4.tgz#bb3faf1e74b74bd547e867e48f551fa6b098b6ce" @@ -131,6 +186,14 @@ "@babel/helper-explode-assignable-expression" "^7.10.3" "@babel/types" "^7.10.3" +"@babel/helper-builder-binary-assignment-operator-visitor@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz#bb0b75f31bf98cbf9ff143c1ae578b87274ae1a3" + integrity sha512-L0zGlFrGWZK4PbT8AszSfLTM5sDU1+Az/En9VrdT8/LmEiJt4zXt+Jve9DCAnQcbqDhCI+29y/L93mrDzddCcg== + dependencies: + "@babel/helper-explode-assignable-expression" "^7.10.4" + "@babel/types" "^7.10.4" + "@babel/helper-builder-binary-assignment-operator-visitor@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.7.4.tgz#5f73f2b28580e224b5b9bd03146a4015d6217f5f" @@ -148,6 +211,15 @@ "@babel/helper-module-imports" "^7.10.1" "@babel/types" "^7.10.1" +"@babel/helper-builder-react-jsx-experimental@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.10.4.tgz#d0ffb875184d749c63ffe1f4f65be15143ec322d" + integrity sha512-LyacH/kgQPgLAuaWrvvq1+E7f5bLyT8jXCh7nM67sRsy2cpIGfgWJ+FCnAKQXfY+F0tXUaN6FqLkp4JiCzdK8Q== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-module-imports" "^7.10.4" + "@babel/types" "^7.10.4" + "@babel/helper-builder-react-jsx@^7.10.3": version "7.10.3" resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.10.3.tgz#62c4b7bb381153a0a5f8d83189b94b9fb5384fc5" @@ -156,13 +228,13 @@ "@babel/helper-annotate-as-pure" "^7.10.1" "@babel/types" "^7.10.3" -"@babel/helper-builder-react-jsx@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.7.4.tgz#da188d247508b65375b2c30cf59de187be6b0c66" - integrity sha512-kvbfHJNN9dg4rkEM4xn1s8d1/h6TYNvajy9L1wx4qLn9HFg0IkTsQi4rfBe92nxrPUFcMsHoMV+8rU7MJb3fCA== +"@babel/helper-builder-react-jsx@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.10.4.tgz#8095cddbff858e6fa9c326daee54a2f2732c1d5d" + integrity sha512-5nPcIZ7+KKDxT1427oBivl9V9YTal7qk0diccnh7RrcgrT/pGFOjgGw1dgryyx1GvHEpXVfoDF6Ak3rTiWh8Rg== dependencies: - "@babel/types" "^7.7.4" - esutils "^2.0.0" + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/types" "^7.10.4" "@babel/helper-call-delegate@^7.7.4": version "7.7.4" @@ -173,6 +245,17 @@ "@babel/traverse" "^7.7.4" "@babel/types" "^7.7.4" +"@babel/helper-compilation-targets@^7.10.4", "@babel/helper-compilation-targets@^7.8.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.10.4.tgz#804ae8e3f04376607cc791b9d47d540276332bd2" + integrity sha512-a3rYhlsGV0UHNDvrtOXBg8/OpfV0OKTkxKPzIplS1zpx7CygDcWWxckxZeDd3gzPzC4kUT0A4nVFDK0wGMh4MQ== + dependencies: + "@babel/compat-data" "^7.10.4" + browserslist "^4.12.0" + invariant "^2.2.4" + levenary "^1.1.1" + semver "^5.5.0" + "@babel/helper-compilation-targets@^7.8.7": version "7.10.2" resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.10.2.tgz#a17d9723b6e2c750299d2a14d4637c76936d8285" @@ -196,6 +279,18 @@ "@babel/helper-replace-supers" "^7.10.1" "@babel/helper-split-export-declaration" "^7.10.1" +"@babel/helper-create-class-features-plugin@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.4.tgz#2d4015d0136bd314103a70d84a7183e4b344a355" + integrity sha512-9raUiOsXPxzzLjCXeosApJItoMnX3uyT4QdM2UldffuGApNrF8e938MwNpDCK9CPoyxrEoCgT+hObJc3mZa6lQ== + dependencies: + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-member-expression-to-functions" "^7.10.4" + "@babel/helper-optimise-call-expression" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-replace-supers" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.10.4" + "@babel/helper-create-class-features-plugin@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.7.4.tgz#fce60939fd50618610942320a8d951b3b639da2d" @@ -217,6 +312,15 @@ "@babel/helper-regex" "^7.10.1" regexpu-core "^4.7.0" +"@babel/helper-create-regexp-features-plugin@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.10.4.tgz#fdd60d88524659a0b6959c0579925e425714f3b8" + integrity sha512-2/hu58IEPKeoLF45DBwx3XFqsbCXmkdAay4spVr2x0jYgRxrSNp+ePwvSsy9g6YSaNDcKIQVPXk1Ov8S2edk2g== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-regex" "^7.10.4" + regexpu-core "^4.7.0" + "@babel/helper-create-regexp-features-plugin@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.7.4.tgz#6d5762359fd34f4da1500e4cff9955b5299aaf59" @@ -234,6 +338,15 @@ "@babel/types" "^7.10.3" lodash "^4.17.13" +"@babel/helper-define-map@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.10.4.tgz#f037ad794264f729eda1889f4ee210b870999092" + integrity sha512-nIij0oKErfCnLUCWaCaHW0Bmtl2RO9cN7+u2QT8yqTywgALKlyUVOvHDElh+b5DwVC6YB1FOYFOTWcN/+41EDA== + dependencies: + "@babel/helper-function-name" "^7.10.4" + "@babel/types" "^7.10.4" + lodash "^4.17.13" + "@babel/helper-define-map@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.7.4.tgz#2841bf92eb8bd9c906851546fe6b9d45e162f176" @@ -251,6 +364,14 @@ "@babel/traverse" "^7.10.3" "@babel/types" "^7.10.3" +"@babel/helper-explode-assignable-expression@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.10.4.tgz#40a1cd917bff1288f699a94a75b37a1a2dbd8c7c" + integrity sha512-4K71RyRQNPRrR85sr5QY4X3VwG4wtVoXZB9+L3r1Gp38DhELyHCtovqydRi7c1Ovb17eRGiQ/FD5s8JdU0Uy5A== + dependencies: + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" + "@babel/helper-explode-assignable-expression@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.7.4.tgz#fa700878e008d85dc51ba43e9fb835cddfe05c84" @@ -268,6 +389,15 @@ "@babel/template" "^7.10.3" "@babel/types" "^7.10.3" +"@babel/helper-function-name@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz#d2d3b20c59ad8c47112fa7d2a94bc09d5ef82f1a" + integrity sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ== + dependencies: + "@babel/helper-get-function-arity" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/types" "^7.10.4" + "@babel/helper-function-name@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz#ab6e041e7135d436d8f0a3eca15de5b67a341a2e" @@ -284,6 +414,13 @@ dependencies: "@babel/types" "^7.10.3" +"@babel/helper-get-function-arity@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz#98c1cbea0e2332f33f9a4661b8ce1505b2c19ba2" + integrity sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A== + dependencies: + "@babel/types" "^7.10.4" + "@babel/helper-get-function-arity@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz#cb46348d2f8808e632f0ab048172130e636005f0" @@ -298,6 +435,13 @@ dependencies: "@babel/types" "^7.10.3" +"@babel/helper-hoist-variables@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz#d49b001d1d5a68ca5e6604dda01a6297f7c9381e" + integrity sha512-wljroF5PgCk2juF69kanHVs6vrLwIPNp6DLD+Lrl3hoQ3PpPPikaDRNFA+0t81NOoMt2DL6WW/mdU8k4k6ZzuA== + dependencies: + "@babel/types" "^7.10.4" + "@babel/helper-hoist-variables@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.7.4.tgz#612384e3d823fdfaaf9fce31550fe5d4db0f3d12" @@ -312,6 +456,13 @@ dependencies: "@babel/types" "^7.10.3" +"@babel/helper-member-expression-to-functions@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.10.4.tgz#7cd04b57dfcf82fce9aeae7d4e4452fa31b8c7c4" + integrity sha512-m5j85pK/KZhuSdM/8cHUABQTAslV47OjfIB9Cc7P+PvlAoBzdb79BGNfw8RhT5Mq3p+xGd0ZfAKixbrUZx0C7A== + dependencies: + "@babel/types" "^7.10.4" + "@babel/helper-member-expression-to-functions@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.7.4.tgz#356438e2569df7321a8326644d4b790d2122cb74" @@ -326,6 +477,13 @@ dependencies: "@babel/types" "^7.10.3" +"@babel/helper-module-imports@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz#4c5c54be04bd31670a7382797d75b9fa2e5b5620" + integrity sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw== + dependencies: + "@babel/types" "^7.10.4" + "@babel/helper-module-imports@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.7.4.tgz#e5a92529f8888bf319a6376abfbd1cebc491ad91" @@ -346,6 +504,19 @@ "@babel/types" "^7.10.1" lodash "^4.17.13" +"@babel/helper-module-transforms@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.10.4.tgz#ca1f01fdb84e48c24d7506bb818c961f1da8805d" + integrity sha512-Er2FQX0oa3nV7eM1o0tNCTx7izmQtwAQsIiaLRWtavAAEcskb0XJ5OjJbVrYXWOTr8om921Scabn4/tzlx7j1Q== + dependencies: + "@babel/helper-module-imports" "^7.10.4" + "@babel/helper-replace-supers" "^7.10.4" + "@babel/helper-simple-access" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/types" "^7.10.4" + lodash "^4.17.13" + "@babel/helper-module-transforms@^7.7.4", "@babel/helper-module-transforms@^7.7.5": version "7.7.5" resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.7.5.tgz#d044da7ffd91ec967db25cd6748f704b6b244835" @@ -365,6 +536,13 @@ dependencies: "@babel/types" "^7.10.3" +"@babel/helper-optimise-call-expression@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz#50dc96413d594f995a77905905b05893cd779673" + integrity sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg== + dependencies: + "@babel/types" "^7.10.4" + "@babel/helper-optimise-call-expression@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.7.4.tgz#034af31370d2995242aa4df402c3b7794b2dcdf2" @@ -382,6 +560,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.3.tgz#aac45cccf8bc1873b99a85f34bceef3beb5d3244" integrity sha512-j/+j8NAWUTxOtx4LKHybpSClxHoq6I91DQ/mKgAXn5oNUPIUiGppjPIX3TDtJWPrdfP9Kfl7e4fgVMiQR9VE/g== +"@babel/helper-plugin-utils@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375" + integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg== + "@babel/helper-regex@^7.0.0", "@babel/helper-regex@^7.4.4": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.5.5.tgz#0aa6824f7100a2e0e89c1527c23936c152cab351" @@ -396,6 +579,13 @@ dependencies: lodash "^4.17.13" +"@babel/helper-regex@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.10.4.tgz#59b373daaf3458e5747dece71bbaf45f9676af6d" + integrity sha512-inWpnHGgtg5NOF0eyHlC0/74/VkdRITY9dtTpB2PrxKKn+AkVMRiZz/Adrx+Ssg+MLDesi2zohBW6MVq6b4pOQ== + dependencies: + lodash "^4.17.13" + "@babel/helper-remap-async-to-generator@^7.10.1", "@babel/helper-remap-async-to-generator@^7.10.3": version "7.10.3" resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.10.3.tgz#18564f8a6748be466970195b876e8bba3bccf442" @@ -407,6 +597,17 @@ "@babel/traverse" "^7.10.3" "@babel/types" "^7.10.3" +"@babel/helper-remap-async-to-generator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.10.4.tgz#fce8bea4e9690bbe923056ded21e54b4e8b68ed5" + integrity sha512-86Lsr6NNw3qTNl+TBcF1oRZMaVzJtbWTyTko+CQL/tvNvcGYEFKbLXDPxtW0HKk3McNOk4KzY55itGWCAGK5tg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-wrap-function" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" + "@babel/helper-remap-async-to-generator@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.7.4.tgz#c68c2407350d9af0e061ed6726afb4fff16d0234" @@ -428,6 +629,16 @@ "@babel/traverse" "^7.10.1" "@babel/types" "^7.10.1" +"@babel/helper-replace-supers@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz#d585cd9388ea06e6031e4cd44b6713cbead9e6cf" + integrity sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.10.4" + "@babel/helper-optimise-call-expression" "^7.10.4" + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" + "@babel/helper-replace-supers@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.7.4.tgz#3c881a6a6a7571275a72d82e6107126ec9e2cdd2" @@ -446,6 +657,14 @@ "@babel/template" "^7.10.1" "@babel/types" "^7.10.1" +"@babel/helper-simple-access@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz#0f5ccda2945277a2a7a2d3a821e15395edcf3461" + integrity sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw== + dependencies: + "@babel/template" "^7.10.4" + "@babel/types" "^7.10.4" + "@babel/helper-simple-access@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.7.4.tgz#a169a0adb1b5f418cfc19f22586b2ebf58a9a294" @@ -461,6 +680,13 @@ dependencies: "@babel/types" "^7.10.1" +"@babel/helper-split-export-declaration@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.4.tgz#2c70576eaa3b5609b24cb99db2888cc3fc4251d1" + integrity sha512-pySBTeoUff56fL5CBU2hWm9TesA4r/rOkI9DyJLvvgz09MB9YtfIYe3iBriVaYNaPe+Alua0vBIOVOLs2buWhg== + dependencies: + "@babel/types" "^7.10.4" + "@babel/helper-split-export-declaration@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz#57292af60443c4a3622cf74040ddc28e68336fd8" @@ -473,6 +699,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.3.tgz#60d9847f98c4cea1b279e005fdb7c28be5412d15" integrity sha512-bU8JvtlYpJSBPuj1VUmKpFGaDZuLxASky3LhaKj3bmpSTY6VWooSM8msk+Z0CZoErFye2tlABF6yDkT3FOPAXw== +"@babel/helper-validator-identifier@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2" + integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw== + "@babel/helper-wrap-function@^7.10.1": version "7.10.1" resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.10.1.tgz#956d1310d6696257a7afd47e4c42dfda5dfcedc9" @@ -483,6 +714,16 @@ "@babel/traverse" "^7.10.1" "@babel/types" "^7.10.1" +"@babel/helper-wrap-function@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.10.4.tgz#8a6f701eab0ff39f765b5a1cfef409990e624b87" + integrity sha512-6py45WvEF0MhiLrdxtRjKjufwLL1/ob2qDJgg5JgNdojBAZSAKnAjkyOCNug6n+OBl4VW76XjvgSFTdaMcW0Ug== + dependencies: + "@babel/helper-function-name" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" + "@babel/helper-wrap-function@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.7.4.tgz#37ab7fed5150e22d9d7266e830072c0cdd8baace" @@ -502,6 +743,15 @@ "@babel/traverse" "^7.10.1" "@babel/types" "^7.10.1" +"@babel/helpers@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.10.4.tgz#2abeb0d721aff7c0a97376b9e1f6f65d7a475044" + integrity sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA== + dependencies: + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" + "@babel/helpers@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.7.4.tgz#62c215b9e6c712dadc15a9a0dcab76c92a940302" @@ -529,6 +779,15 @@ chalk "^2.0.0" js-tokens "^4.0.0" +"@babel/highlight@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.4.tgz#7d1bdfd65753538fabe6c38596cdb76d9ac60143" + integrity sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA== + dependencies: + "@babel/helper-validator-identifier" "^7.10.4" + chalk "^2.0.0" + js-tokens "^4.0.0" + "@babel/parser@^7.0.0", "@babel/parser@^7.7.4", "@babel/parser@^7.7.7": version "7.7.7" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.7.tgz#1b886595419cf92d811316d5b715a53ff38b4937" @@ -539,6 +798,20 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.10.3.tgz#7e71d892b0d6e7d04a1af4c3c79d72c1f10f5315" integrity sha512-oJtNJCMFdIMwXGmx+KxuaD7i3b8uS7TTFYW/FNG2BT8m+fmGHoiPYoH0Pe3gya07WuFmM5FCDIr1x0irkD/hyA== +"@babel/parser@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.10.4.tgz#9eedf27e1998d87739fb5028a5120557c06a1a64" + integrity sha512-8jHII4hf+YVDsskTF6WuMB3X4Eh+PsUkC2ljq22so5rHvH+T8BzyL94VOdyFLNR8tBSVXOTbNHOKpR4TfRxVtA== + +"@babel/plugin-proposal-async-generator-functions@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.4.tgz#4b65abb3d9bacc6c657aaa413e56696f9f170fc6" + integrity sha512-MJbxGSmejEFVOANAezdO39SObkURO5o/8b6fSH6D1pi9RZQt+ldppKPXfqgUWpSQ9asM6xaSaSJIaeWMDRP0Zg== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-remap-async-to-generator" "^7.10.4" + "@babel/plugin-syntax-async-generators" "^7.8.0" + "@babel/plugin-proposal-async-generator-functions@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.7.4.tgz#0351c5ac0a9e927845fffd5b82af476947b7ce6d" @@ -565,6 +838,14 @@ "@babel/helper-create-class-features-plugin" "^7.8.3" "@babel/helper-plugin-utils" "^7.8.3" +"@babel/plugin-proposal-class-properties@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.10.4.tgz#a33bf632da390a59c7a8c570045d1115cd778807" + integrity sha512-vhwkEROxzcHGNu2mzUC0OFFNXdZ4M23ib8aRRcJSsW8BZK9pQMD7QB7csl97NBbgGZO7ZyHUyKDnxzOaP4IrCg== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-proposal-decorators@7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.8.3.tgz#2156860ab65c5abf068c3f67042184041066543e" @@ -574,6 +855,14 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-decorators" "^7.8.3" +"@babel/plugin-proposal-dynamic-import@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.10.4.tgz#ba57a26cb98b37741e9d5bca1b8b0ddf8291f17e" + integrity sha512-up6oID1LeidOOASNXgv/CFbgBqTuKJ0cJjz6An5tWD+NVBNlp3VNSBxv2ZdU7SYl3NxJC7agAQDApZusV6uFwQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-dynamic-import" "^7.8.0" + "@babel/plugin-proposal-dynamic-import@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.7.4.tgz#dde64a7f127691758cbfed6cf70de0fa5879d52d" @@ -590,6 +879,14 @@ "@babel/helper-plugin-utils" "^7.10.1" "@babel/plugin-syntax-dynamic-import" "^7.8.0" +"@babel/plugin-proposal-json-strings@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.10.4.tgz#593e59c63528160233bd321b1aebe0820c2341db" + integrity sha512-fCL7QF0Jo83uy1K0P2YXrfX11tj3lkpN7l4dMv9Y9VkowkhkQDwFHFd8IiwyK5MZjE8UpbgokkgtcReH88Abaw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-json-strings" "^7.8.0" + "@babel/plugin-proposal-json-strings@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.7.4.tgz#7700a6bfda771d8dc81973249eac416c6b4c697d" @@ -614,6 +911,14 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" +"@babel/plugin-proposal-nullish-coalescing-operator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.10.4.tgz#02a7e961fc32e6d5b2db0649e01bf80ddee7e04a" + integrity sha512-wq5n1M3ZUlHl9sqT2ok1T2/MTt6AXE0e1Lz4WzWBr95LsAZ5qDXe4KnFuauYyEyLiohvXFMdbsOTMyLZs91Zlw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" + "@babel/plugin-proposal-nullish-coalescing-operator@^7.8.3": version "7.10.1" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.10.1.tgz#02dca21673842ff2fe763ac253777f235e9bbf78" @@ -630,6 +935,14 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-numeric-separator" "^7.8.3" +"@babel/plugin-proposal-numeric-separator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.10.4.tgz#ce1590ff0a65ad12970a609d78855e9a4c1aef06" + integrity sha512-73/G7QoRoeNkLZFxsoCCvlg4ezE4eM+57PnOqgaPOozd5myfj7p0muD1mRVJvbUWbOzD+q3No2bWbaKy+DJ8DA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + "@babel/plugin-proposal-numeric-separator@^7.8.3": version "7.10.1" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.10.1.tgz#a9a38bc34f78bdfd981e791c27c6fdcec478c123" @@ -638,6 +951,15 @@ "@babel/helper-plugin-utils" "^7.10.1" "@babel/plugin-syntax-numeric-separator" "^7.10.1" +"@babel/plugin-proposal-object-rest-spread@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.10.4.tgz#50129ac216b9a6a55b3853fdd923e74bf553a4c0" + integrity sha512-6vh4SqRuLLarjgeOf4EaROJAHjvu9Gl+/346PbDH9yWbJyfnJ/ah3jmYKYtswEyCoWZiidvVHjHshd4WgjB9BA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-object-rest-spread" "^7.8.0" + "@babel/plugin-transform-parameters" "^7.10.4" + "@babel/plugin-proposal-object-rest-spread@^7.7.7": version "7.7.7" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.7.7.tgz#9f27075004ab99be08c5c1bd653a2985813cb370" @@ -655,6 +977,14 @@ "@babel/plugin-syntax-object-rest-spread" "^7.8.0" "@babel/plugin-transform-parameters" "^7.10.1" +"@babel/plugin-proposal-optional-catch-binding@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.10.4.tgz#31c938309d24a78a49d68fdabffaa863758554dd" + integrity sha512-LflT6nPh+GK2MnFiKDyLiqSqVHkQnVf7hdoAvyTnnKj9xB3docGRsdPuxp6qqqW19ifK3xgc9U5/FwrSaCNX5g== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" + "@babel/plugin-proposal-optional-catch-binding@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.7.4.tgz#ec21e8aeb09ec6711bc0a39ca49520abee1de379" @@ -679,6 +1009,14 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-optional-chaining" "^7.8.0" +"@babel/plugin-proposal-optional-chaining@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.10.4.tgz#750f1255e930a1f82d8cdde45031f81a0d0adff7" + integrity sha512-ZIhQIEeavTgouyMSdZRap4VPPHqJJ3NEs2cuHs5p0erH+iz6khB0qfgU8g7UuJkG88+fBMy23ZiU+nuHvekJeQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-optional-chaining" "^7.8.0" + "@babel/plugin-proposal-optional-chaining@^7.9.0": version "7.10.3" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.10.3.tgz#9a726f94622b653c0a3a7a59cdce94730f526f7c" @@ -687,6 +1025,22 @@ "@babel/helper-plugin-utils" "^7.10.3" "@babel/plugin-syntax-optional-chaining" "^7.8.0" +"@babel/plugin-proposal-private-methods@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.10.4.tgz#b160d972b8fdba5c7d111a145fc8c421fc2a6909" + integrity sha512-wh5GJleuI8k3emgTg5KkJK6kHNsGEr0uBTDBuQUBJwckk9xs1ez79ioheEVVxMLyPscB0LfkbVHslQqIzWV6Bw== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-proposal-unicode-property-regex@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.10.4.tgz#4483cda53041ce3413b7fe2f00022665ddfaa75d" + integrity sha512-H+3fOgPnEXFL9zGYtKQe4IDOPKYlZdF1kqFDQRRb8PK4B8af1vAGK04tF5iQAAsui+mHNBQSAtd2/ndEDe9wuA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-proposal-unicode-property-regex@^7.4.4", "@babel/plugin-proposal-unicode-property-regex@^7.8.3": version "7.10.1" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.10.1.tgz#dc04feb25e2dd70c12b05d680190e138fa2c0c6f" @@ -724,6 +1078,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" +"@babel/plugin-syntax-class-properties@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.10.4.tgz#6644e6a0baa55a61f9e3231f6c9eeb6ee46c124c" + integrity sha512-GCSBF7iUle6rNugfURwNmCGG3Z/2+opxAMLs1nND4bhEG5PuxTIggDBoeYYSujAlLtsupzOHYJQgPS3pivwXIA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-class-properties@^7.8.3": version "7.10.1" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.10.1.tgz#d5bc0645913df5b17ad7eda0fa2308330bde34c5" @@ -794,12 +1155,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.1" -"@babel/plugin-syntax-jsx@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.7.4.tgz#dab2b56a36fb6c3c222a1fbc71f7bf97f327a9ec" - integrity sha512-wuy6fiMe9y7HeZBWXYCGt2RGxZOj0BImZ9EyXJVnVGBKO/Br592rbR3rtIQn0eQhAk9vqaKP5n8tVqEFBQMfLg== +"@babel/plugin-syntax-jsx@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.10.4.tgz#39abaae3cbf710c4373d8429484e6ba21340166c" + integrity sha512-KCg9mio9jwiARCB7WAcQ7Y1q+qicILjoK8LP/VkPkEKaf5dkaZZK1EcTe91a3JJlZ3qy6L5s9X52boEYi8DM9g== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-logical-assignment-operators@^7.8.3": version "7.10.1" @@ -822,6 +1183,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.1" +"@babel/plugin-syntax-numeric-separator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-object-rest-spread@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.7.4.tgz#47cf220d19d6d0d7b154304701f468fc1cc6ff46" @@ -857,6 +1225,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" +"@babel/plugin-syntax-top-level-await@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.10.4.tgz#4bbeb8917b54fcf768364e0a81f560e33a3ef57d" + integrity sha512-ni1brg4lXEmWyafKr0ccFWkJG0CeMt4WV1oyeBW6EFObF4oOHclbkj5cARxAPQyAQ2UTuplJyK4nfkXIMMFvsQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-top-level-await@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.7.4.tgz#bd7d8fa7b9fee793a36e4027fd6dd1aa32f946da" @@ -885,6 +1260,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-arrow-functions@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.10.4.tgz#e22960d77e697c74f41c501d44d73dbf8a6a64cd" + integrity sha512-9J/oD1jV0ZCBcgnoFWFq1vJd4msoKb/TCpGNFyyLt0zABdcvgK3aYikZ8HjzB14c26bc7E3Q1yugpwGy2aTPNA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-arrow-functions@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.7.4.tgz#76309bd578addd8aee3b379d809c802305a98a12" @@ -899,6 +1281,15 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.1" +"@babel/plugin-transform-async-to-generator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.10.4.tgz#41a5017e49eb6f3cda9392a51eef29405b245a37" + integrity sha512-F6nREOan7J5UXTLsDsZG3DXmZSVofr2tGNwfdrVwkDWHfQckbQXnXSPfD7iO+c/2HGqycwyLST3DnZ16n+cBJQ== + dependencies: + "@babel/helper-module-imports" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-remap-async-to-generator" "^7.10.4" + "@babel/plugin-transform-async-to-generator@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.7.4.tgz#694cbeae6d613a34ef0292713fa42fb45c4470ba" @@ -917,6 +1308,13 @@ "@babel/helper-plugin-utils" "^7.10.1" "@babel/helper-remap-async-to-generator" "^7.10.1" +"@babel/plugin-transform-block-scoped-functions@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.10.4.tgz#1afa595744f75e43a91af73b0d998ecfe4ebc2e8" + integrity sha512-WzXDarQXYYfjaV1szJvN3AD7rZgZzC1JtjJZ8dMHUyiK8mxPRahynp14zzNjU3VkPqPsO38CzxiWO1c9ARZ8JA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-block-scoped-functions@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.7.4.tgz#d0d9d5c269c78eaea76227ace214b8d01e4d837b" @@ -931,6 +1329,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.1" +"@babel/plugin-transform-block-scoping@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.10.4.tgz#a670d1364bb5019a621b9ea2001482876d734787" + integrity sha512-J3b5CluMg3hPUii2onJDRiaVbPtKFPLEaV5dOPY5OeAbDi1iU/UbbFFTgwb7WnanaDy7bjU35kc26W3eM5Qa0A== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + lodash "^4.17.13" + "@babel/plugin-transform-block-scoping@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.7.4.tgz#200aad0dcd6bb80372f94d9e628ea062c58bf224" @@ -947,6 +1353,20 @@ "@babel/helper-plugin-utils" "^7.10.1" lodash "^4.17.13" +"@babel/plugin-transform-classes@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.10.4.tgz#405136af2b3e218bc4a1926228bc917ab1a0adc7" + integrity sha512-2oZ9qLjt161dn1ZE0Ms66xBncQH4In8Sqw1YWgBUZuGVJJS5c0OFZXL6dP2MRHrkU/eKhWg8CzFJhRQl50rQxA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-define-map" "^7.10.4" + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-optimise-call-expression" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-replace-supers" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.10.4" + globals "^11.1.0" + "@babel/plugin-transform-classes@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.7.4.tgz#c92c14be0a1399e15df72667067a8f510c9400ec" @@ -975,6 +1395,13 @@ "@babel/helper-split-export-declaration" "^7.10.1" globals "^11.1.0" +"@babel/plugin-transform-computed-properties@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.10.4.tgz#9ded83a816e82ded28d52d4b4ecbdd810cdfc0eb" + integrity sha512-JFwVDXcP/hM/TbyzGq3l/XWGut7p46Z3QvqFMXTfk6/09m7xZHJUN9xHfsv7vqqD4YnfI5ueYdSJtXqqBLyjBw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-computed-properties@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.7.4.tgz#e856c1628d3238ffe12d668eb42559f79a81910d" @@ -989,6 +1416,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.3" +"@babel/plugin-transform-destructuring@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.10.4.tgz#70ddd2b3d1bea83d01509e9bb25ddb3a74fc85e5" + integrity sha512-+WmfvyfsyF603iPa6825mq6Qrb7uLjTOsa3XOFzlYcYDHSS4QmpOWOL0NNBY5qMbvrcf3tq0Cw+v4lxswOBpgA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-destructuring@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.7.4.tgz#2b713729e5054a1135097b6a67da1b6fe8789267" @@ -1003,6 +1437,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.1" +"@babel/plugin-transform-dotall-regex@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.10.4.tgz#469c2062105c1eb6a040eaf4fac4b488078395ee" + integrity sha512-ZEAVvUTCMlMFAbASYSVQoxIbHm2OkG2MseW6bV2JjIygOjdVv8tuxrCTzj1+Rynh7ODb8GivUy7dzEXzEhuPaA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-dotall-regex@^7.4.4", "@babel/plugin-transform-dotall-regex@^7.8.3": version "7.10.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.10.1.tgz#920b9fec2d78bb57ebb64a644d5c2ba67cc104ee" @@ -1019,6 +1461,13 @@ "@babel/helper-create-regexp-features-plugin" "^7.7.4" "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-duplicate-keys@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.10.4.tgz#697e50c9fee14380fe843d1f306b295617431e47" + integrity sha512-GL0/fJnmgMclHiBTTWXNlYjYsA7rDrtsazHG6mglaGSTh0KsrW04qml+Bbz9FL0LcJIRwBWL5ZqlNHKTkU3xAA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-duplicate-keys@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.7.4.tgz#3d21731a42e3f598a73835299dd0169c3b90ac91" @@ -1033,6 +1482,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.1" +"@babel/plugin-transform-exponentiation-operator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.10.4.tgz#5ae338c57f8cf4001bdb35607ae66b92d665af2e" + integrity sha512-S5HgLVgkBcRdyQAHbKj+7KyuWx8C6t5oETmUuwz1pt3WTWJhsUV0WIIXuVvfXMxl/QQyHKlSCNNtaIamG8fysw== + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-exponentiation-operator@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.7.4.tgz#dd30c0191e3a1ba19bcc7e389bdfddc0729d5db9" @@ -1065,6 +1522,13 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-flow" "^7.7.4" +"@babel/plugin-transform-for-of@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.10.4.tgz#c08892e8819d3a5db29031b115af511dbbfebae9" + integrity sha512-ItdQfAzu9AlEqmusA/65TqJ79eRcgGmpPPFvBnGILXZH975G0LNjP1yjHvGgfuCxqrPPueXOPe+FsvxmxKiHHQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-for-of@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.7.4.tgz#248800e3a5e507b1f103d8b4ca998e77c63932bc" @@ -1079,6 +1543,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.1" +"@babel/plugin-transform-function-name@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.10.4.tgz#6a467880e0fc9638514ba369111811ddbe2644b7" + integrity sha512-OcDCq2y5+E0dVD5MagT5X+yTRbcvFjDI2ZVAottGH6tzqjx/LKpgkUepu3hp/u4tZBzxxpNGwLsAvGBvQ2mJzg== + dependencies: + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-function-name@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.7.4.tgz#75a6d3303d50db638ff8b5385d12451c865025b1" @@ -1095,6 +1567,13 @@ "@babel/helper-function-name" "^7.10.1" "@babel/helper-plugin-utils" "^7.10.1" +"@babel/plugin-transform-literals@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.10.4.tgz#9f42ba0841100a135f22712d0e391c462f571f3c" + integrity sha512-Xd/dFSTEVuUWnyZiMu76/InZxLTYilOSr1UlHV+p115Z/Le2Fi1KXkJUYz0b42DfndostYlPub3m8ZTQlMaiqQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-literals@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.7.4.tgz#27fe87d2b5017a2a5a34d1c41a6b9f6a6262643e" @@ -1109,6 +1588,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.1" +"@babel/plugin-transform-member-expression-literals@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.10.4.tgz#b1ec44fcf195afcb8db2c62cd8e551c881baf8b7" + integrity sha512-0bFOvPyAoTBhtcJLr9VcwZqKmSjFml1iVxvPL0ReomGU53CX53HsM4h2SzckNdkQcHox1bpAqzxBI1Y09LlBSw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-member-expression-literals@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.7.4.tgz#aee127f2f3339fc34ce5e3055d7ffbf7aa26f19a" @@ -1123,6 +1609,15 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.1" +"@babel/plugin-transform-modules-amd@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.10.4.tgz#cb407c68b862e4c1d13a2fc738c7ec5ed75fc520" + integrity sha512-3Fw+H3WLUrTlzi3zMiZWp3AR4xadAEMv6XRCYnd5jAlLM61Rn+CRJaZMaNvIpcJpQ3vs1kyifYvEVPFfoSkKOA== + dependencies: + "@babel/helper-module-transforms" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + babel-plugin-dynamic-import-node "^2.3.3" + "@babel/plugin-transform-modules-amd@^7.7.5": version "7.7.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.7.5.tgz#39e0fb717224b59475b306402bb8eedab01e729c" @@ -1151,6 +1646,16 @@ "@babel/helper-simple-access" "^7.7.4" babel-plugin-dynamic-import-node "^2.3.0" +"@babel/plugin-transform-modules-commonjs@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.10.4.tgz#66667c3eeda1ebf7896d41f1f16b17105a2fbca0" + integrity sha512-Xj7Uq5o80HDLlW64rVfDBhao6OX89HKUmb+9vWYaLXBZOma4gA6tw4Ni1O5qVDoZWUV0fxMYA0aYzOawz0l+1w== + dependencies: + "@babel/helper-module-transforms" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-simple-access" "^7.10.4" + babel-plugin-dynamic-import-node "^2.3.3" + "@babel/plugin-transform-modules-commonjs@^7.9.0": version "7.10.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.10.1.tgz#d5ff4b4413ed97ffded99961056e1fb980fb9301" @@ -1161,6 +1666,16 @@ "@babel/helper-simple-access" "^7.10.1" babel-plugin-dynamic-import-node "^2.3.3" +"@babel/plugin-transform-modules-systemjs@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.10.4.tgz#8f576afd943ac2f789b35ded0a6312f929c633f9" + integrity sha512-Tb28LlfxrTiOTGtZFsvkjpyjCl9IoaRI52AEU/VIwOwvDQWtbNJsAqTXzh+5R7i74e/OZHH2c2w2fsOqAfnQYQ== + dependencies: + "@babel/helper-hoist-variables" "^7.10.4" + "@babel/helper-module-transforms" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + babel-plugin-dynamic-import-node "^2.3.3" + "@babel/plugin-transform-modules-systemjs@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.7.4.tgz#cd98152339d3e763dfe838b7d4273edaf520bb30" @@ -1180,6 +1695,14 @@ "@babel/helper-plugin-utils" "^7.10.3" babel-plugin-dynamic-import-node "^2.3.3" +"@babel/plugin-transform-modules-umd@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.10.4.tgz#9a8481fe81b824654b3a0b65da3df89f3d21839e" + integrity sha512-mohW5q3uAEt8T45YT7Qc5ws6mWgJAaL/8BfWD9Dodo1A3RKWli8wTS+WiQ/knF+tXlPirW/1/MqzzGfCExKECA== + dependencies: + "@babel/helper-module-transforms" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-modules-umd@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.7.4.tgz#1027c355a118de0aae9fee00ad7813c584d9061f" @@ -1196,6 +1719,13 @@ "@babel/helper-module-transforms" "^7.10.1" "@babel/helper-plugin-utils" "^7.10.1" +"@babel/plugin-transform-named-capturing-groups-regex@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.10.4.tgz#78b4d978810b6f3bcf03f9e318f2fc0ed41aecb6" + integrity sha512-V6LuOnD31kTkxQPhKiVYzYC/Jgdq53irJC/xBSmqcNcqFGV+PER4l6rU5SH2Vl7bH9mLDHcc0+l9HUOe4RNGKA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.10.4" + "@babel/plugin-transform-named-capturing-groups-regex@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.7.4.tgz#fb3bcc4ee4198e7385805007373d6b6f42c98220" @@ -1210,6 +1740,13 @@ dependencies: "@babel/helper-create-regexp-features-plugin" "^7.8.3" +"@babel/plugin-transform-new-target@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.10.4.tgz#9097d753cb7b024cb7381a3b2e52e9513a9c6888" + integrity sha512-YXwWUDAH/J6dlfwqlWsztI2Puz1NtUAubXhOPLQ5gjR/qmQ5U96DY4FQO8At33JN4XPBhrjB8I4eMmLROjjLjw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-new-target@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.7.4.tgz#4a0753d2d60639437be07b592a9e58ee00720167" @@ -1224,6 +1761,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.1" +"@babel/plugin-transform-object-super@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.10.4.tgz#d7146c4d139433e7a6526f888c667e314a093894" + integrity sha512-5iTw0JkdRdJvr7sY0vHqTpnruUpTea32JHmq/atIWqsnNussbRzjEDyWep8UNztt1B5IusBYg8Irb0bLbiEBCQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-replace-supers" "^7.10.4" + "@babel/plugin-transform-object-super@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.7.4.tgz#48488937a2d586c0148451bf51af9d7dda567262" @@ -1248,6 +1793,14 @@ "@babel/helper-get-function-arity" "^7.10.1" "@babel/helper-plugin-utils" "^7.10.1" +"@babel/plugin-transform-parameters@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.10.4.tgz#7b4d137c87ea7adc2a0f3ebf53266871daa6fced" + integrity sha512-RurVtZ/D5nYfEg0iVERXYKEgDFeesHrHfx8RT05Sq57ucj2eOYAP6eu5fynL4Adju4I/mP/I6SO0DqNWAXjfLQ== + dependencies: + "@babel/helper-get-function-arity" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-parameters@^7.7.7": version "7.7.7" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.7.7.tgz#7a884b2460164dc5f194f668332736584c760007" @@ -1257,6 +1810,13 @@ "@babel/helper-get-function-arity" "^7.7.4" "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-property-literals@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.10.4.tgz#f6fe54b6590352298785b83edd815d214c42e3c0" + integrity sha512-ofsAcKiUxQ8TY4sScgsGeR2vJIsfrzqvFb9GvJ5UdXDzl+MyYCaBj/FGzXuv7qE0aJcjWMILny1epqelnFlz8g== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-property-literals@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.7.4.tgz#2388d6505ef89b266103f450f9167e6bd73f98c2" @@ -1278,6 +1838,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" +"@babel/plugin-transform-react-display-name@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.10.4.tgz#b5795f4e3e3140419c3611b7a2a3832b9aef328d" + integrity sha512-Zd4X54Mu9SBfPGnEcaGcOrVAYOtjT2on8QZkLKEq1S/tHexG39d9XXGZv19VfRrDjPJzFmPfTAqOQS1pfFOujw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-react-display-name@^7.8.3": version "7.10.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.10.3.tgz#e3c246e1b4f3e52cc7633e237ad9194c0ec482e7" @@ -1285,6 +1852,15 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.3" +"@babel/plugin-transform-react-jsx-development@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.10.4.tgz#6ec90f244394604623880e15ebc3c34c356258ba" + integrity sha512-RM3ZAd1sU1iQ7rI2dhrZRZGv0aqzNQMbkIUCS1txYpi9wHQ2ZHNjo5TwX+UD6pvFW4AbWqLVYvKy5qJSAyRGjQ== + dependencies: + "@babel/helper-builder-react-jsx-experimental" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-jsx" "^7.10.4" + "@babel/plugin-transform-react-jsx-development@^7.9.0": version "7.10.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.10.1.tgz#1ac6300d8b28ef381ee48e6fec430cc38047b7f3" @@ -1294,6 +1870,14 @@ "@babel/helper-plugin-utils" "^7.10.1" "@babel/plugin-syntax-jsx" "^7.10.1" +"@babel/plugin-transform-react-jsx-self@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.10.4.tgz#cd301a5fed8988c182ed0b9d55e9bd6db0bd9369" + integrity sha512-yOvxY2pDiVJi0axdTWHSMi5T0DILN+H+SaeJeACHKjQLezEzhLx9nEF9xgpBLPtkZsks9cnb5P9iBEi21En3gg== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-jsx" "^7.10.4" + "@babel/plugin-transform-react-jsx-self@^7.9.0": version "7.10.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.10.1.tgz#22143e14388d72eb88649606bb9e46f421bc3821" @@ -1302,6 +1886,14 @@ "@babel/helper-plugin-utils" "^7.10.1" "@babel/plugin-syntax-jsx" "^7.10.1" +"@babel/plugin-transform-react-jsx-source@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.10.4.tgz#86baf0fcccfe58084e06446a80858e1deae8f291" + integrity sha512-FTK3eQFrPv2aveerUSazFmGygqIdTtvskG50SnGnbEUnRPcGx2ylBhdFIzoVS1ty44hEgcPoCAyw5r3VDEq+Ug== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-jsx" "^7.10.4" + "@babel/plugin-transform-react-jsx-source@^7.9.0": version "7.10.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.10.1.tgz#30db3d4ee3cdebbb26a82a9703673714777a4273" @@ -1310,14 +1902,15 @@ "@babel/helper-plugin-utils" "^7.10.1" "@babel/plugin-syntax-jsx" "^7.10.1" -"@babel/plugin-transform-react-jsx@^7.0.0": - version "7.7.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.7.7.tgz#5cbaa7445b4a09f774029f3cc7bb448ff3122a5d" - integrity sha512-SlPjWPbva2+7/ZJbGcoqjl4LsQaLpKEzxW9hcxU7675s24JmdotJOSJ4cgAbV82W3FcZpHIGmRZIlUL8ayMvjw== +"@babel/plugin-transform-react-jsx@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.10.4.tgz#673c9f913948764a4421683b2bef2936968fddf2" + integrity sha512-L+MfRhWjX0eI7Js093MM6MacKU4M6dnCRa/QPDwYMxjljzSCzzlzKzj9Pk4P3OtrPcxr2N3znR419nr3Xw+65A== dependencies: - "@babel/helper-builder-react-jsx" "^7.7.4" - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-jsx" "^7.7.4" + "@babel/helper-builder-react-jsx" "^7.10.4" + "@babel/helper-builder-react-jsx-experimental" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-jsx" "^7.10.4" "@babel/plugin-transform-react-jsx@^7.9.1": version "7.10.3" @@ -1329,6 +1922,21 @@ "@babel/helper-plugin-utils" "^7.10.3" "@babel/plugin-syntax-jsx" "^7.10.1" +"@babel/plugin-transform-react-pure-annotations@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.10.4.tgz#3eefbb73db94afbc075f097523e445354a1c6501" + integrity sha512-+njZkqcOuS8RaPakrnR9KvxjoG1ASJWpoIv/doyWngId88JoFlPlISenGXjrVacZUIALGUr6eodRs1vmPnF23A== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-regenerator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.10.4.tgz#2015e59d839074e76838de2159db421966fd8b63" + integrity sha512-3thAHwtor39A7C04XucbMg17RcZ3Qppfxr22wYzZNcVIkPHfpM9J0SO8zuCV6SZa265kxBJSrfKTvDCYqBFXGw== + dependencies: + regenerator-transform "^0.14.2" + "@babel/plugin-transform-regenerator@^7.7.5": version "7.7.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.7.5.tgz#3a8757ee1a2780f390e89f246065ecf59c26fce9" @@ -1343,6 +1951,13 @@ dependencies: regenerator-transform "^0.14.2" +"@babel/plugin-transform-reserved-words@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.10.4.tgz#8f2682bcdcef9ed327e1b0861585d7013f8a54dd" + integrity sha512-hGsw1O6Rew1fkFbDImZIEqA8GoidwTAilwCyWqLBM9f+e/u/sQMQu7uX6dyokfOayRuuVfKOW4O7HvaBWM+JlQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-reserved-words@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.7.4.tgz#6a7cf123ad175bb5c69aec8f6f0770387ed3f1eb" @@ -1367,6 +1982,13 @@ resolve "^1.8.1" semver "^5.5.1" +"@babel/plugin-transform-shorthand-properties@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.10.4.tgz#9fd25ec5cdd555bb7f473e5e6ee1c971eede4dd6" + integrity sha512-AC2K/t7o07KeTIxMoHneyX90v3zkm5cjHJEokrPEAGEy3UCp8sLKfnfOIGdZ194fyN4wfX/zZUWT9trJZ0qc+Q== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-shorthand-properties@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.7.4.tgz#74a0a9b2f6d67a684c6fbfd5f0458eb7ba99891e" @@ -1381,6 +2003,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.1" +"@babel/plugin-transform-spread@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.10.4.tgz#4e2c85ea0d6abaee1b24dcfbbae426fe8d674cff" + integrity sha512-1e/51G/Ni+7uH5gktbWv+eCED9pP8ZpRhZB3jOaI3mmzfvJTWHkuyYTv0Z5PYtyM+Tr2Ccr9kUdQxn60fI5WuQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-spread@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.7.4.tgz#aa673b356fe6b7e70d69b6e33a17fef641008578" @@ -1395,6 +2024,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.1" +"@babel/plugin-transform-sticky-regex@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.10.4.tgz#8f3889ee8657581130a29d9cc91d7c73b7c4a28d" + integrity sha512-Ddy3QZfIbEV0VYcVtFDCjeE4xwVTJWTmUtorAJkn6u/92Z/nWJNV+mILyqHKrUxXYKA2EoCilgoPePymKL4DvQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-regex" "^7.10.4" + "@babel/plugin-transform-sticky-regex@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.7.4.tgz#ffb68c05090c30732076b1285dc1401b404a123c" @@ -1411,6 +2048,14 @@ "@babel/helper-plugin-utils" "^7.10.1" "@babel/helper-regex" "^7.10.1" +"@babel/plugin-transform-template-literals@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.10.4.tgz#e6375407b30fcb7fcfdbba3bb98ef3e9d36df7bc" + integrity sha512-4NErciJkAYe+xI5cqfS8pV/0ntlY5N5Ske/4ImxAVX7mk9Rxt2bwDTGv1Msc2BRJvWQcmYEC+yoMLdX22aE4VQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-template-literals@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.7.4.tgz#1eb6411736dd3fe87dbd20cc6668e5121c17d604" @@ -1427,6 +2072,13 @@ "@babel/helper-annotate-as-pure" "^7.10.1" "@babel/helper-plugin-utils" "^7.10.3" +"@babel/plugin-transform-typeof-symbol@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.10.4.tgz#9509f1a7eec31c4edbffe137c16cc33ff0bc5bfc" + integrity sha512-QqNgYwuuW0y0H+kUE/GWSR45t/ccRhe14Fs/4ZRouNNQsyd4o3PG4OtHiIrepbM2WKUBDAXKCAK/Lk4VhzTaGA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-typeof-symbol@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.7.4.tgz#3174626214f2d6de322882e498a38e8371b2140e" @@ -1459,6 +2111,21 @@ "@babel/helper-plugin-utils" "^7.10.3" "@babel/plugin-syntax-typescript" "^7.10.1" +"@babel/plugin-transform-unicode-escapes@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.10.4.tgz#feae523391c7651ddac115dae0a9d06857892007" + integrity sha512-y5XJ9waMti2J+e7ij20e+aH+fho7Wb7W8rNuu72aKRwCHFqQdhkdU2lo3uZ9tQuboEJcUFayXdARhcxLQ3+6Fg== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-unicode-regex@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.10.4.tgz#e56d71f9282fac6db09c82742055576d5e6d80a8" + integrity sha512-wNfsc4s8N2qnIwpO/WP2ZiSyjfpTamT2C9V9FDH/Ljub9zw6P3SjkXcFmc0RQUt96k2fmIvtla2MMjgTwIAC+A== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-unicode-regex@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.7.4.tgz#a3c0f65b117c4c81c5b6484f2a5e7b95346b83ae" @@ -1598,6 +2265,76 @@ js-levenshtein "^1.1.3" semver "^5.5.0" +"@babel/preset-env@^7.4.0": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.10.4.tgz#fbf57f9a803afd97f4f32e4f798bb62e4b2bef5f" + integrity sha512-tcmuQ6vupfMZPrLrc38d0sF2OjLT3/bZ0dry5HchNCQbrokoQi4reXqclvkkAT5b+gWc23meVWpve5P/7+w/zw== + dependencies: + "@babel/compat-data" "^7.10.4" + "@babel/helper-compilation-targets" "^7.10.4" + "@babel/helper-module-imports" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-proposal-async-generator-functions" "^7.10.4" + "@babel/plugin-proposal-class-properties" "^7.10.4" + "@babel/plugin-proposal-dynamic-import" "^7.10.4" + "@babel/plugin-proposal-json-strings" "^7.10.4" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.10.4" + "@babel/plugin-proposal-numeric-separator" "^7.10.4" + "@babel/plugin-proposal-object-rest-spread" "^7.10.4" + "@babel/plugin-proposal-optional-catch-binding" "^7.10.4" + "@babel/plugin-proposal-optional-chaining" "^7.10.4" + "@babel/plugin-proposal-private-methods" "^7.10.4" + "@babel/plugin-proposal-unicode-property-regex" "^7.10.4" + "@babel/plugin-syntax-async-generators" "^7.8.0" + "@babel/plugin-syntax-class-properties" "^7.10.4" + "@babel/plugin-syntax-dynamic-import" "^7.8.0" + "@babel/plugin-syntax-json-strings" "^7.8.0" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + "@babel/plugin-syntax-object-rest-spread" "^7.8.0" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" + "@babel/plugin-syntax-optional-chaining" "^7.8.0" + "@babel/plugin-syntax-top-level-await" "^7.10.4" + "@babel/plugin-transform-arrow-functions" "^7.10.4" + "@babel/plugin-transform-async-to-generator" "^7.10.4" + "@babel/plugin-transform-block-scoped-functions" "^7.10.4" + "@babel/plugin-transform-block-scoping" "^7.10.4" + "@babel/plugin-transform-classes" "^7.10.4" + "@babel/plugin-transform-computed-properties" "^7.10.4" + "@babel/plugin-transform-destructuring" "^7.10.4" + "@babel/plugin-transform-dotall-regex" "^7.10.4" + "@babel/plugin-transform-duplicate-keys" "^7.10.4" + "@babel/plugin-transform-exponentiation-operator" "^7.10.4" + "@babel/plugin-transform-for-of" "^7.10.4" + "@babel/plugin-transform-function-name" "^7.10.4" + "@babel/plugin-transform-literals" "^7.10.4" + "@babel/plugin-transform-member-expression-literals" "^7.10.4" + "@babel/plugin-transform-modules-amd" "^7.10.4" + "@babel/plugin-transform-modules-commonjs" "^7.10.4" + "@babel/plugin-transform-modules-systemjs" "^7.10.4" + "@babel/plugin-transform-modules-umd" "^7.10.4" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.10.4" + "@babel/plugin-transform-new-target" "^7.10.4" + "@babel/plugin-transform-object-super" "^7.10.4" + "@babel/plugin-transform-parameters" "^7.10.4" + "@babel/plugin-transform-property-literals" "^7.10.4" + "@babel/plugin-transform-regenerator" "^7.10.4" + "@babel/plugin-transform-reserved-words" "^7.10.4" + "@babel/plugin-transform-shorthand-properties" "^7.10.4" + "@babel/plugin-transform-spread" "^7.10.4" + "@babel/plugin-transform-sticky-regex" "^7.10.4" + "@babel/plugin-transform-template-literals" "^7.10.4" + "@babel/plugin-transform-typeof-symbol" "^7.10.4" + "@babel/plugin-transform-unicode-escapes" "^7.10.4" + "@babel/plugin-transform-unicode-regex" "^7.10.4" + "@babel/preset-modules" "^0.1.3" + "@babel/types" "^7.10.4" + browserslist "^4.12.0" + core-js-compat "^3.6.2" + invariant "^2.2.2" + levenary "^1.1.1" + semver "^5.5.0" + "@babel/preset-modules@^0.1.3": version "0.1.3" resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.3.tgz#13242b53b5ef8c883c3cf7dddd55b36ce80fbc72" @@ -1621,6 +2358,19 @@ "@babel/plugin-transform-react-jsx-self" "^7.9.0" "@babel/plugin-transform-react-jsx-source" "^7.9.0" +"@babel/preset-react@^7.0.0": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.10.4.tgz#92e8a66d816f9911d11d4cc935be67adfc82dbcf" + integrity sha512-BrHp4TgOIy4M19JAfO1LhycVXOPWdDbTRep7eVyatf174Hff+6Uk53sDyajqZPu8W1qXRBiYOfIamek6jA7YVw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-react-display-name" "^7.10.4" + "@babel/plugin-transform-react-jsx" "^7.10.4" + "@babel/plugin-transform-react-jsx-development" "^7.10.4" + "@babel/plugin-transform-react-jsx-self" "^7.10.4" + "@babel/plugin-transform-react-jsx-source" "^7.10.4" + "@babel/plugin-transform-react-pure-annotations" "^7.10.4" + "@babel/preset-typescript@7.9.0": version "7.9.0" resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.9.0.tgz#87705a72b1f0d59df21c179f7c3d2ef4b16ce192" @@ -1669,6 +2419,15 @@ "@babel/parser" "^7.10.3" "@babel/types" "^7.10.3" +"@babel/template@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.4.tgz#3251996c4200ebc71d1a8fc405fba940f36ba278" + integrity sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/parser" "^7.10.4" + "@babel/types" "^7.10.4" + "@babel/traverse@^7.0.0", "@babel/traverse@^7.2.3", "@babel/traverse@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.7.4.tgz#9c1e7c60fb679fe4fcfaa42500833333c2058558" @@ -1699,6 +2458,21 @@ globals "^11.1.0" lodash "^4.17.13" +"@babel/traverse@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.10.4.tgz#e642e5395a3b09cc95c8e74a27432b484b697818" + integrity sha512-aSy7p5THgSYm4YyxNGz6jZpXf+Ok40QF3aA2LyIONkDHpAcJzDUqlCKXv6peqYUs2gmic849C/t2HKw2a2K20Q== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.10.4" + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.10.4" + "@babel/parser" "^7.10.4" + "@babel/types" "^7.10.4" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.13" + "@babel/types@^7.0.0", "@babel/types@^7.3.3", "@babel/types@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.7.4.tgz#516570d539e44ddf308c07569c258ff94fde9193" @@ -1717,6 +2491,15 @@ lodash "^4.17.13" to-fast-properties "^2.0.0" +"@babel/types@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.10.4.tgz#369517188352e18219981efd156bfdb199fff1ee" + integrity sha512-UTCFOxC3FsFHb7lkRMVvgLzaRVamXuAs2Tz4wajva4WxtVY82eZeaUBtC2Zt95FU9TiznuC0Zk35tsim8jeVpg== + dependencies: + "@babel/helper-validator-identifier" "^7.10.4" + lodash "^4.17.13" + to-fast-properties "^2.0.0" + "@bcoe/v8-coverage@^0.2.3": version "0.2.3" resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" @@ -1956,437 +2739,536 @@ "@nodelib/fs.scandir" "2.1.3" fastq "^1.6.0" -"@parcel/babel-preset-env@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/babel-preset-env/-/babel-preset-env-2.0.0-alpha.3.1.tgz#57de8cac436023f16a74858904a9fab1b7886714" - integrity sha512-OXxuA+B113MDWMuOrsIbMBZOZ3uVs+jHseNYae6MT34Op63wistpP9Xlzv8DBChgbZyPS7bPpYYyf8ZK5Da0LA== +"@parcel/babel-ast-utils@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/babel-ast-utils/-/babel-ast-utils-2.0.0-beta.1.tgz#e545b5db02d95d32f321e5e12137175935c57615" + integrity sha512-0Jod0KZ2gCghymjP7ThI/2DfZQt9S2yq1wTvBwyJ46Ij3lIZVmXBVWs4x8O0uvKMUjS5zrnSFgurimFORLmDbQ== dependencies: - "@babel/preset-env" "^7.0.0" + "@babel/generator" "^7.0.0" + "@babel/parser" "^7.0.0" + "@parcel/source-map" "2.0.0-alpha.4.13" + "@parcel/utils" "2.0.0-beta.1" + +"@parcel/babel-preset-env@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/babel-preset-env/-/babel-preset-env-2.0.0-beta.1.tgz#562837d4c28c271a0e30bc5970ef63965ddc82dc" + integrity sha512-/TK/xE9Rfy6weu0eWifnGCntCt4i7DoFCKgigdSsHbuRA4w7BfnwS0GIOAQ6gORRXIf4lM8cGsnp5jRP2PhwLw== + dependencies: + "@babel/preset-env" "^7.4.0" semver "^5.4.1" -"@parcel/bundler-default@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/bundler-default/-/bundler-default-2.0.0-alpha.3.1.tgz#33f318d826989f517e4753c249fdf807de339433" - integrity sha512-p21dHAEn5ewFZ6ZhDL8faKnBobrPVO/3O/uo4yxedQp4Lmf7pVGAo6C9rZEM2HB7pJjCeQBmLVsGdFn0mMZT8w== +"@parcel/babylon-walk@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/babylon-walk/-/babylon-walk-2.0.0-beta.1.tgz#feada450c819c67e3552c184c6b30f914a7f54d0" + integrity sha512-FWZErHc2Q62lrWxfMoRl1mej8HCr3tXvzeVgMfv2cbiOjaZIrN+8khD0AcRyesnm5JipgT8KQoJvl8ZdU9DFAw== dependencies: - "@parcel/plugin" "^2.0.0-alpha.3.1" - "@parcel/utils" "^2.0.0-alpha.3.1" + "@babel/types" "^7.0.0" + lodash.clone "^4.5.0" + +"@parcel/bundler-default@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/bundler-default/-/bundler-default-2.0.0-beta.1.tgz#66a6762d6bb1fd8c8c9d13177f5fabe1fbf5a196" + integrity sha512-ksRBQcZ4OQwZ+pWl28V/G5z6JR/fZUSdXSJwyVJKCUQhKLp0qVZ0emYnZFLg+24ITemRosPH9tNMyQwzNWugsw== + dependencies: + "@parcel/plugin" "2.0.0-beta.1" + "@parcel/utils" "2.0.0-beta.1" nullthrows "^1.1.1" -"@parcel/cache@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/cache/-/cache-2.0.0-alpha.3.1.tgz#4d3db941a9ffa2b788cf52009bfa9069fa2aafdf" - integrity sha512-KI+mj/YEFxZyCCTcUoyXrS4nEI0CD/HvaayuNt/5QuAZmkJ3iDw0vo5nS8xC9VGL94cZZHG4qZWDigQvHI5vZQ== +"@parcel/cache@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/cache/-/cache-2.0.0-beta.1.tgz#4a69d58f2acdff050256e2f23518d219cd29a089" + integrity sha512-o8GMPcrVH31uctXQGGX6O28T7Bm4dqM0DbJRCDtxixGQosKyN9OlAA84390XOti2Fjr1Av/U1ALmbdavQsdcYA== dependencies: - "@parcel/logger" "^2.0.0-alpha.3.1" - "@parcel/utils" "^2.0.0-alpha.3.1" + "@parcel/logger" "2.0.0-beta.1" + "@parcel/utils" "2.0.0-beta.1" -"@parcel/codeframe@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/codeframe/-/codeframe-2.0.0-alpha.3.1.tgz#0dd4b2f6c2f1fdb283c5b407ae7b96ce94cd4418" - integrity sha512-Y7orGAw9qvrH86RBxpSuidIfR13uqoH/RoeBr3vq4CIYFW6K6JunEWTGAstV5hpuY6pzk7mv2xxhNCUkIYBIFg== +"@parcel/codeframe@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/codeframe/-/codeframe-2.0.0-beta.1.tgz#5c1195131b653562d2362f4056767694a1a6f736" + integrity sha512-HyFjYSPysYumT/T3JdZN8y0DXhXLMpmlg94rADR+Wf5Wp1YMTuIHlE1gkfbjIj1m2PxJWe4UMbniGwy3KQh9zQ== dependencies: chalk "^2.4.2" emphasize "^2.1.0" + slice-ansi "^4.0.0" + string-width "^4.2.0" -"@parcel/config-default@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/config-default/-/config-default-2.0.0-alpha.3.1.tgz#459e9b28001fa8de2631b4ead4e3292d093ced17" - integrity sha512-tQfvLIzAuASnyoUX0cD2jBr8bcpsZMeFCeZWAWu715b9dHmZ3FHlD6tzsV18O6V+7lMCqJfLDg3vPBGvDA79mA== - dependencies: - "@parcel/bundler-default" "^2.0.0-alpha.3.1" - "@parcel/namer-default" "^2.0.0-alpha.3.1" - "@parcel/optimizer-cssnano" "^2.0.0-alpha.3.1" - "@parcel/optimizer-data-url" "^2.0.0-alpha.3.1" - "@parcel/optimizer-htmlnano" "^2.0.0-alpha.3.1" - "@parcel/optimizer-terser" "^2.0.0-alpha.3.1" - "@parcel/packager-css" "^2.0.0-alpha.3.1" - "@parcel/packager-html" "^2.0.0-alpha.3.1" - "@parcel/packager-js" "^2.0.0-alpha.3.1" - "@parcel/packager-raw" "^2.0.0-alpha.3.1" - "@parcel/packager-ts" "^2.0.0-alpha.3.1" - "@parcel/reporter-cli" "^2.0.0-alpha.3.1" - "@parcel/reporter-dev-server" "^2.0.0-alpha.3.1" - "@parcel/reporter-hmr-server" "^2.0.0-alpha.3.1" - "@parcel/resolver-default" "^2.0.0-alpha.3.1" - "@parcel/runtime-browser-hmr" "^2.0.0-alpha.3.1" - "@parcel/runtime-js" "^2.0.0-alpha.3.1" - "@parcel/runtime-react-refresh" "^2.0.0-alpha.3.1" - "@parcel/transformer-babel" "^2.0.0-alpha.3.1" - "@parcel/transformer-coffeescript" "^2.0.0-alpha.3.1" - "@parcel/transformer-css" "^2.0.0-alpha.3.1" - "@parcel/transformer-graphql" "^2.0.0-alpha.3.1" - "@parcel/transformer-html" "^2.0.0-alpha.3.1" - "@parcel/transformer-inline-string" "^2.0.0-alpha.3.1" - "@parcel/transformer-js" "^2.0.0-alpha.3.1" - "@parcel/transformer-json" "^2.0.0-alpha.3.1" - "@parcel/transformer-less" "^2.0.0-alpha.3.1" - "@parcel/transformer-postcss" "^2.0.0-alpha.3.1" - "@parcel/transformer-posthtml" "^2.0.0-alpha.3.1" - "@parcel/transformer-pug" "^2.0.0-alpha.3.1" - "@parcel/transformer-raw" "^2.0.0-alpha.3.1" - "@parcel/transformer-react-refresh-babel" "^2.0.0-alpha.3.1" - "@parcel/transformer-react-refresh-wrap" "^2.0.0-alpha.3.1" - "@parcel/transformer-sass" "^2.0.0-alpha.3.1" - "@parcel/transformer-stylus" "^2.0.0-alpha.3.1" - "@parcel/transformer-sugarss" "^2.0.0-alpha.3.1" - "@parcel/transformer-toml" "^2.0.0-alpha.3.1" - "@parcel/transformer-typescript-types" "^2.0.0-alpha.3.1" - "@parcel/transformer-yaml" "^2.0.0-alpha.3.1" - -"@parcel/core@^2.0.0-alpha.3.2": - version "2.0.0-alpha.3.2" - resolved "https://registry.yarnpkg.com/@parcel/core/-/core-2.0.0-alpha.3.2.tgz#28ef7b464556803f0454fc46316530d1cd4524ef" - integrity sha512-Nnr4GOmx0mzUhSLu6MvBpPJDA3YhgWPDwpw1uH/80vRXqLYrX1sZCnOYjGGhoWi7VrYjoHVak+FZLrZrhUlGmw== - dependencies: - "@parcel/cache" "^2.0.0-alpha.3.1" - "@parcel/diagnostic" "^2.0.0-alpha.3.1" - "@parcel/events" "^2.0.0-alpha.3.1" - "@parcel/fs" "^2.0.0-alpha.3.1" - "@parcel/logger" "^2.0.0-alpha.3.1" - "@parcel/package-manager" "^2.0.0-alpha.3.1" - "@parcel/plugin" "^2.0.0-alpha.3.1" - "@parcel/source-map" "^2.0.0-alpha.3.1" - "@parcel/types" "^2.0.0-alpha.3.1" - "@parcel/utils" "^2.0.0-alpha.3.1" - "@parcel/workers" "^2.0.0-alpha.3.1" +"@parcel/config-default@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/config-default/-/config-default-2.0.0-beta.1.tgz#ddea69c182ee1105e4682161cf0541d81680b66d" + integrity sha512-VEJYkiF+RNaB28OPmk1sCsOapWPisu5MXV+8N7T5ERa7xOOaD2SbD5/JnOjuUGAYKALk8UBsTCG+3ukMQ7Fiuw== + dependencies: + "@parcel/bundler-default" "2.0.0-beta.1" + "@parcel/namer-default" "2.0.0-beta.1" + "@parcel/optimizer-cssnano" "2.0.0-beta.1" + "@parcel/optimizer-data-url" "2.0.0-beta.1" + "@parcel/optimizer-htmlnano" "2.0.0-beta.1" + "@parcel/optimizer-terser" "2.0.0-beta.1" + "@parcel/packager-css" "2.0.0-beta.1" + "@parcel/packager-html" "2.0.0-beta.1" + "@parcel/packager-js" "2.0.0-beta.1" + "@parcel/packager-raw" "2.0.0-beta.1" + "@parcel/packager-raw-url" "2.0.0-beta.1" + "@parcel/packager-ts" "2.0.0-beta.1" + "@parcel/reporter-bundle-analyzer" "2.0.0-beta.1" + "@parcel/reporter-bundle-buddy" "2.0.0-beta.1" + "@parcel/reporter-cli" "2.0.0-beta.1" + "@parcel/reporter-dev-server" "2.0.0-beta.1" + "@parcel/resolver-default" "2.0.0-beta.1" + "@parcel/runtime-browser-hmr" "2.0.0-beta.1" + "@parcel/runtime-js" "2.0.0-beta.1" + "@parcel/runtime-react-refresh" "2.0.0-beta.1" + "@parcel/transformer-babel" "2.0.0-beta.1" + "@parcel/transformer-coffeescript" "2.0.0-beta.1" + "@parcel/transformer-css" "2.0.0-beta.1" + "@parcel/transformer-graphql" "2.0.0-beta.1" + "@parcel/transformer-html" "2.0.0-beta.1" + "@parcel/transformer-inline-string" "2.0.0-beta.1" + "@parcel/transformer-js" "2.0.0-beta.1" + "@parcel/transformer-json" "2.0.0-beta.1" + "@parcel/transformer-jsonld" "2.0.0-beta.1" + "@parcel/transformer-less" "2.0.0-beta.1" + "@parcel/transformer-mdx" "2.0.0-beta.1" + "@parcel/transformer-postcss" "2.0.0-beta.1" + "@parcel/transformer-posthtml" "2.0.0-beta.1" + "@parcel/transformer-pug" "2.0.0-beta.1" + "@parcel/transformer-raw" "2.0.0-beta.1" + "@parcel/transformer-react-refresh-babel" "2.0.0-beta.1" + "@parcel/transformer-react-refresh-wrap" "2.0.0-beta.1" + "@parcel/transformer-sass" "2.0.0-beta.1" + "@parcel/transformer-stylus" "2.0.0-beta.1" + "@parcel/transformer-sugarss" "2.0.0-beta.1" + "@parcel/transformer-toml" "2.0.0-beta.1" + "@parcel/transformer-typescript-types" "2.0.0-beta.1" + "@parcel/transformer-yaml" "2.0.0-beta.1" + +"@parcel/core@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/core/-/core-2.0.0-beta.1.tgz#d1cf4352a954c6dbe2b31543f937902ba6cf3848" + integrity sha512-1KKjhL2H7z8qJNgY2M3CreYqbKopJT6ImlJk54ynIrLuJsnqKuA80FHYBiAtnSZEA65mvAJ3YLReFhg9slzbFw== + dependencies: + "@parcel/cache" "2.0.0-beta.1" + "@parcel/diagnostic" "2.0.0-beta.1" + "@parcel/events" "2.0.0-beta.1" + "@parcel/fs" "2.0.0-beta.1" + "@parcel/logger" "2.0.0-beta.1" + "@parcel/package-manager" "2.0.0-beta.1" + "@parcel/plugin" "2.0.0-beta.1" + "@parcel/source-map" "2.0.0-alpha.4.13" + "@parcel/types" "2.0.0-beta.1" + "@parcel/utils" "2.0.0-beta.1" + "@parcel/workers" "2.0.0-beta.1" abortcontroller-polyfill "^1.1.9" browserslist "^4.6.6" clone "^2.1.1" dotenv "^7.0.0" dotenv-expand "^5.1.0" + json-source-map "^0.6.1" json5 "^1.0.1" micromatch "^4.0.2" nullthrows "^1.1.1" - pirates "^4.0.0" semver "^5.4.1" -"@parcel/diagnostic@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/diagnostic/-/diagnostic-2.0.0-alpha.3.1.tgz#005376248503ad40e7c84f004e3d2b69e7c17bf7" - integrity sha512-45kRMFXFu5LZm77dJ8SJdPF4RdpP+zCBC2Q/ebXWvbgLKJOyapAtnFFvdwCS4xfbvL2xOrC4gEsP0SCvZTVKWQ== +"@parcel/diagnostic@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/diagnostic/-/diagnostic-2.0.0-beta.1.tgz#0616cf75fd8e294643fe13b204ad1e60b42bb66d" + integrity sha512-LNfe2MgbKiqXnEws1QT9tANeg6iw+u6hNnuO2ZjRdnAIF/LqslD/6RKryE1yD1lh71ezACwLscji0CLuys6mbg== dependencies: json-source-map "^0.6.1" nullthrows "^1.1.1" -"@parcel/events@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/events/-/events-2.0.0-alpha.3.1.tgz#a287e415d12920745b5ac6e11b86c2e51d44a8ee" - integrity sha512-s3f54ppFRTxHNZ4cMaqJBf6qYWHEI/Jo6pD//4XU3VTMLyUC9pAj+rEVx7vZi7fAye7FKC5aLsrvFp4dby/pTA== +"@parcel/events@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/events/-/events-2.0.0-beta.1.tgz#8f7c2276dab1938f6d47d2d2a64a1fde0b58b7eb" + integrity sha512-m//K2aHYnr4tSONlUmS0HhNQtmhYjCUJ+dv85mfLEqLlQVmsLBwxlcqBS5M1ONlaGPlI87xUKY8uBTg8kY1q4g== -"@parcel/fs@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/fs/-/fs-2.0.0-alpha.3.1.tgz#06fdf709f1412727e6ebd267ee42f5a9119aa0b4" - integrity sha512-DHXGRX/D9F2RgKecN6Fh7KmqLWD+IQxEraURF4hxw/QCfdQiUaobPS65I3VG7GLRhTeEXMjDibPF5902FJiQuQ== +"@parcel/fs-write-stream-atomic@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/fs-write-stream-atomic/-/fs-write-stream-atomic-2.0.0-beta.1.tgz#158fb2cb4bf56342bce71841794616909bc50300" + integrity sha512-ZL3da/3jhMvu6ZwZBmxEiGXOLq+qvVvvx6DVv+4JQV0EMAFp7gvD4CH0QKLCgKBbjd1wqEBPyW3CCEo5tGtAHA== dependencies: - "@parcel/utils" "^2.0.0-alpha.3.1" - "@parcel/watcher" "^2.0.0-alpha.4" - "@parcel/workers" "^2.0.0-alpha.3.1" + graceful-fs "^4.1.2" + iferr "^1.0.2" + imurmurhash "^0.1.4" + readable-stream "1 || 2" + +"@parcel/fs@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/fs/-/fs-2.0.0-beta.1.tgz#bbe3ab36736cca7399804fa38e5daa553f9ec723" + integrity sha512-THLgnN+eaxfa4s0T3KIuOB1N4Lg5lwlz2Y1Y69vWujZh3B3PHbNDlJ4n0O0m+vgYZoJZ43X+qxId0yeHUh6p0w== + dependencies: + "@parcel/fs-write-stream-atomic" "2.0.0-beta.1" + "@parcel/utils" "2.0.0-beta.1" + "@parcel/watcher" "^2.0.0-alpha.5" + "@parcel/workers" "2.0.0-beta.1" mkdirp "^0.5.1" ncp "^2.0.0" nullthrows "^1.1.1" rimraf "^2.6.2" -"@parcel/logger@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/logger/-/logger-2.0.0-alpha.3.1.tgz#f0ea5b912419bc2e2aaf78cbbb8dff53d727cfa0" - integrity sha512-+Lyk1rtiyezoZor6yKq4lnbfIIQD0pdSSPhomKOa+yTpnWZVLjNZ/QJ+Q4PocJtN+VLOzw23nbPsTKeDTAYtEQ== +"@parcel/logger@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/logger/-/logger-2.0.0-beta.1.tgz#a987e863db6d5ba02092894c2ef92bce74d9ea23" + integrity sha512-PMhAs1vCPSDKt977w0cMNCEHjBTy94Khc1Pr07/YXwiijxzDBxPS9JmV8dBbryTheRy/EyUhJDXES3brQwiiqw== dependencies: - "@parcel/diagnostic" "^2.0.0-alpha.3.1" - "@parcel/events" "^2.0.0-alpha.3.1" + "@parcel/diagnostic" "2.0.0-beta.1" + "@parcel/events" "2.0.0-beta.1" -"@parcel/markdown-ansi@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/markdown-ansi/-/markdown-ansi-2.0.0-alpha.3.1.tgz#b06db6c592c3bcd1a6163efaf3b625d686c973c3" - integrity sha512-e88oynbkLr/l8mbANhtlxwfTFV0O7QZrKz9g+WTWOdouJZz/vEYb1Au4BjdyMiT+H0WXtlFSAJC6XzIaMeZxZA== +"@parcel/markdown-ansi@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/markdown-ansi/-/markdown-ansi-2.0.0-beta.1.tgz#3dc3a805a475f560328cdbb2ef3ea892e468905a" + integrity sha512-J1r4m7LczK+X26p/tjA+9VP0g4vzYNUlUyFvIHt7dcdSVEjLM2ICUQZSIzlRHXlVQ+ciMxOFUYtDBCzAzXiLfQ== dependencies: chalk "^2.4.2" -"@parcel/namer-default@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/namer-default/-/namer-default-2.0.0-alpha.3.1.tgz#c74a929166fb35ce1a72d65fc5e5a07262327f0e" - integrity sha512-w3zB+pvdWSa+an3sYLE74+b2Es1JSX+lcUFM2I0fL996GL0EZiu4teYiN0Bet0sxBlTJdrrnxhIAEGzVtA9B+w== +"@parcel/namer-default@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/namer-default/-/namer-default-2.0.0-beta.1.tgz#f8c018648f3991e537462fa7f73925cac19b3276" + integrity sha512-b3In/s++ykB/EL2CLAFWEx0/GUaQ0TMXAfpLfd9wCmqsJq1MQxW437aujF5bIDNHjEE7+rnGk4XP+IO9uViWpQ== dependencies: - "@parcel/plugin" "^2.0.0-alpha.3.1" + "@parcel/diagnostic" "2.0.0-beta.1" + "@parcel/plugin" "2.0.0-beta.1" nullthrows "^1.1.1" -"@parcel/optimizer-cssnano@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/optimizer-cssnano/-/optimizer-cssnano-2.0.0-alpha.3.1.tgz#09e8a7fe55a5a16b5a7f35874334dbfcb7b899e8" - integrity sha512-t/rBVgOt6wJ6jd0C7+D0zXcUWSHMPh3YnvcM516INtZJ7t/RrQZM5Z9+hUvD8u1nEDzAKqblLvgAn2q7enNP9g== +"@parcel/node-libs-browser@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/node-libs-browser/-/node-libs-browser-2.0.0-beta.1.tgz#7004d99e2e76b238c362ca1262f30c74e3f36c84" + integrity sha512-U9pS9KwhTluA9atSzU4X5173BXRER7BRqPSSAEBrfAbCeIfzAG1d1+bhyMZs3SBSt6afWU5HBy//wB8OWBqcKw== dependencies: - "@parcel/plugin" "^2.0.0-alpha.3.1" + assert "^2.0.0" + browserify-zlib "^0.2.0" + buffer "^5.5.0" + console-browserify "^1.2.0" + constants-browserify "^1.0.0" + crypto-browserify "^3.12.0" + domain-browser "^3.5.0" + events "^3.1.0" + https-browserify "^1.0.0" + os-browserify "^0.3.0" + path-browserify "^1.0.0" + process "^0.11.10" + punycode "^1.4.1" + querystring-es3 "^0.2.1" + readable-stream "^3.6.0" + stream-http "^3.1.0" + string_decoder "^1.3.0" + timers-browserify "^2.0.11" + tty-browserify "^0.0.1" + url "^0.11.0" + util "^0.12.3" + vm-browserify "^1.1.2" + +"@parcel/node-resolver-core@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/node-resolver-core/-/node-resolver-core-2.0.0-beta.1.tgz#012234b691fe2a913210544b2be538875cd16614" + integrity sha512-A2Eu+TEnh90Q+iisNfKmaHTPbIR/eshRUqze8PFvSTKv+n9ejNOJ0GCb+x/PFqeqavJRXUBFc60F2pAp88+Bjw== + dependencies: + "@parcel/diagnostic" "2.0.0-beta.1" + "@parcel/node-libs-browser" "2.0.0-beta.1" + "@parcel/utils" "2.0.0-beta.1" + micromatch "^3.0.4" + nullthrows "^1.1.1" + +"@parcel/optimizer-cssnano@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/optimizer-cssnano/-/optimizer-cssnano-2.0.0-beta.1.tgz#a233d16e8330c2cf17fc897b9feb5265ccddccaf" + integrity sha512-f7Yz7kWAVvhRmT/QXNFrlR//pE7D1+G4iWYKstUFWJP0SsoquQBUsb3NI6vltUvydN6htcCRHGX9GhAnHRpaFw== + dependencies: + "@parcel/plugin" "2.0.0-beta.1" + "@parcel/source-map" "2.0.0-alpha.4.13" cssnano "^4.1.10" postcss "^7.0.5" -"@parcel/optimizer-data-url@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/optimizer-data-url/-/optimizer-data-url-2.0.0-alpha.3.1.tgz#16e9eac5e6ce87afa6191135766c6484006afc1f" - integrity sha512-1PXp/kjRELe8ie7DHYz3QDDTumaJs3a8WFb3DzYM87VdgB23YEXvoaFgtM04QW17zF8rnH2PqT6HnPeJcYe3bg== +"@parcel/optimizer-data-url@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/optimizer-data-url/-/optimizer-data-url-2.0.0-beta.1.tgz#17491b755e0a66492888be2ab0f774519502107e" + integrity sha512-H+oMRbBsYXm0GEpzwkaNO3VMxmt50yIg9IE3dyAkXDIZ4kOpaDxYJkGuuR51L5BzQSbEeXwipzoqd2LoLJ8O6w== dependencies: - "@parcel/plugin" "^2.0.0-alpha.3.1" - "@parcel/utils" "^2.0.0-alpha.3.1" + "@parcel/plugin" "2.0.0-beta.1" + "@parcel/utils" "2.0.0-beta.1" isbinaryfile "^4.0.2" mime "^2.4.4" -"@parcel/optimizer-htmlnano@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/optimizer-htmlnano/-/optimizer-htmlnano-2.0.0-alpha.3.1.tgz#3d726b24eea653e25c3d92a4df02c3789d3aeed7" - integrity sha512-Qpw+KLlVhfi/F5DX5mCpYTjJ9vvVrGUSjM+TG6rOcpkPjZnE/7zYtck5Z9IHc78/dUjwFthMQR9R3dBi6aCqOA== +"@parcel/optimizer-htmlnano@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/optimizer-htmlnano/-/optimizer-htmlnano-2.0.0-beta.1.tgz#8716b21983dcaa87165c1d89b822f8e918805822" + integrity sha512-Mz8gkvOd6pyazQFmOjGugz6Q8ydxqjeA6PyrE21/cTj8CtmLCs4TCfEzLcU79qHyr8a+KVx4roTCUwTGv+J/7Q== dependencies: - "@parcel/plugin" "^2.0.0-alpha.3.1" - "@parcel/utils" "^2.0.0-alpha.3.1" + "@parcel/plugin" "2.0.0-beta.1" + "@parcel/utils" "2.0.0-beta.1" htmlnano "^0.2.2" nullthrows "^1.1.1" posthtml "^0.11.3" -"@parcel/optimizer-terser@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/optimizer-terser/-/optimizer-terser-2.0.0-alpha.3.1.tgz#633acdcf4b0817da9dc3d61e955ea2edbba7f9b3" - integrity sha512-gNs2ubWubwsARLYexqztYzw6xwvDUzD4HHkIEAg3WIVUSXyBeaaZXiCzBM2wjzLh14WXFc6BmlHSlqeFBNCe/g== +"@parcel/optimizer-terser@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/optimizer-terser/-/optimizer-terser-2.0.0-beta.1.tgz#0f5c9e95e3a56675763d532db3dc470b12aedbe5" + integrity sha512-S6uu4Q4L8NV+TQes35dQmHqcA6NaRmQSI0vl75IGSaTJnvnq/M3fvrTUd6Xp4dOt/eLh4UJEH7F01TbO1KFZwg== dependencies: - "@parcel/plugin" "^2.0.0-alpha.3.1" - "@parcel/source-map" "^2.0.0-alpha.3.1" - "@parcel/utils" "^2.0.0-alpha.3.1" + "@parcel/diagnostic" "2.0.0-beta.1" + "@parcel/plugin" "2.0.0-beta.1" + "@parcel/source-map" "2.0.0-alpha.4.13" + "@parcel/utils" "2.0.0-beta.1" nullthrows "^1.1.1" - terser "^4.0.0" - -"@parcel/package-manager@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/package-manager/-/package-manager-2.0.0-alpha.3.1.tgz#e413d0385ea5fcdcfd391bffd836fd742d8cf277" - integrity sha512-5rU0A7cMoNpiZx3fJh9cL+eDqOe5jlSBrFuEp864ZcKTkCoiyysZPza0Hmm368Q0nclcm9ueaR/Dgm2WXgVK7g== - dependencies: - "@parcel/fs" "^2.0.0-alpha.3.1" - "@parcel/logger" "^2.0.0-alpha.3.1" - "@parcel/utils" "^2.0.0-alpha.3.1" - "@parcel/workers" "^2.0.0-alpha.3.1" + terser "^4.3.0" + +"@parcel/package-manager@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/package-manager/-/package-manager-2.0.0-beta.1.tgz#7da4b67df8c91e2e5284c5f0a0bf36cf220dc644" + integrity sha512-3i7YXkR0TjJ7RcDpLV5ki5PLsBcdux9BILctC3LLQbNrW5kZjwztEOCnaHJbcQ3VaHaLu6znU8y24EPoyBOPMA== + dependencies: + "@parcel/diagnostic" "2.0.0-beta.1" + "@parcel/fs" "2.0.0-beta.1" + "@parcel/logger" "2.0.0-beta.1" + "@parcel/utils" "2.0.0-beta.1" + "@parcel/workers" "2.0.0-beta.1" command-exists "^1.2.6" cross-spawn "^6.0.4" nullthrows "^1.1.1" resolve "^1.12.0" + semver "^5.4.1" split2 "^3.1.1" -"@parcel/packager-css@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/packager-css/-/packager-css-2.0.0-alpha.3.1.tgz#210c176c5fdc5e99682d8df59429586137fee70f" - integrity sha512-IvQ8PBC0fPlHvc0SM1BINqNwMqoYS3/yeuxTs0DJ+gnEmbcSwOsxhJT7LoAOne3LUjGjOVmvmHXpItCmqXciiQ== +"@parcel/packager-css@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/packager-css/-/packager-css-2.0.0-beta.1.tgz#374bcf0af5736694bb35a11137152e2829610326" + integrity sha512-oi69yNnSZTuQ8y8GuHOFgZ9qQ5oBktNuOEhOoHd7Y15Srior/SwPjx0/UypBweEiKRGApipJtrgo0XQvr5x9aQ== dependencies: - "@parcel/plugin" "^2.0.0-alpha.3.1" - "@parcel/utils" "^2.0.0-alpha.3.1" + "@parcel/plugin" "2.0.0-beta.1" + "@parcel/source-map" "2.0.0-alpha.4.13" + "@parcel/utils" "2.0.0-beta.1" -"@parcel/packager-html@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/packager-html/-/packager-html-2.0.0-alpha.3.1.tgz#5f7c2c05cea2f8ffe3a76444839c5f7e1ed91d99" - integrity sha512-tpM20z1OUp1J9q8u+aJb61f622vI4J+nGNhVYN6hUQpZLYHWbPYvgms36MCr7uSQrhUZSDmdWCSEKeyHGy0Ltg== +"@parcel/packager-html@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/packager-html/-/packager-html-2.0.0-beta.1.tgz#c10d341702b4957f17b4c9e30af1a8362a9fd947" + integrity sha512-ixuLWNpFGNYCKHbrhx2mY/aal1ORJyjaOozCLx2jL5888JeCw34jCWZcXSej+hc50KICr/RVd/WrA5v6YvkBMA== dependencies: - "@parcel/plugin" "^2.0.0-alpha.3.1" - "@parcel/types" "^2.0.0-alpha.3.1" - "@parcel/utils" "^2.0.0-alpha.3.1" + "@parcel/plugin" "2.0.0-beta.1" + "@parcel/types" "2.0.0-beta.1" + "@parcel/utils" "2.0.0-beta.1" nullthrows "^1.1.1" posthtml "^0.11.3" -"@parcel/packager-js@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/packager-js/-/packager-js-2.0.0-alpha.3.1.tgz#3848224646a3f77c69966bab9e3490a1f52f5883" - integrity sha512-NpsSXFMV37lklq1m+YOnz2x066ePpJ7mibeDm8zev3cF7Gev0AH8f9zUChV2lMBNdRUnPTKz4ZVNnyDXt4KhIA== +"@parcel/packager-js@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/packager-js/-/packager-js-2.0.0-beta.1.tgz#4ddf768fe1f3b3ae9dea10291d3d563734a45d90" + integrity sha512-4sWVYv/uPDokftaMquZa1f70wE5O85bcRklcs0kUGPjWNf3uaCG/tS6h9USD2GDbcdjY1xDNoClu6EUTM1AvhA== dependencies: - "@parcel/plugin" "^2.0.0-alpha.3.1" - "@parcel/scope-hoisting" "^2.0.0-alpha.3.1" - "@parcel/source-map" "^2.0.0-alpha.3.1" - "@parcel/utils" "^2.0.0-alpha.3.1" + "@babel/traverse" "^7.2.3" + "@parcel/plugin" "2.0.0-beta.1" + "@parcel/scope-hoisting" "2.0.0-beta.1" + "@parcel/source-map" "2.0.0-alpha.4.13" + "@parcel/utils" "2.0.0-beta.1" + nullthrows "^1.1.1" + +"@parcel/packager-raw-url@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/packager-raw-url/-/packager-raw-url-2.0.0-beta.1.tgz#fb3378bf28f77cc84a27efbf0b7d191a4d06c354" + integrity sha512-elXRSp0ig1Q4y2xMpp3AGPVPFHOB0dW/qT3FbXJwBQhUtjOJrfOtQUlT59l0xP57pADS2aihgnQx0Vl13lL7FQ== + dependencies: + "@parcel/plugin" "2.0.0-beta.1" + "@parcel/utils" "2.0.0-beta.1" -"@parcel/packager-raw@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/packager-raw/-/packager-raw-2.0.0-alpha.3.1.tgz#789d9c354f3e6835ef19b8fb725f42cd0749837e" - integrity sha512-TGyXie5wiwYr4nYqqH606gGmf60/ch3f3MxkCktpaAdKxZLs4ku7io1MUQlg6y7ft7AuCO8+5CNw+A0m37uDyw== +"@parcel/packager-raw@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/packager-raw/-/packager-raw-2.0.0-beta.1.tgz#3e3c574e6134a94d77ead5a850151716986b645c" + integrity sha512-Os8m1DuPfGqjcR4avbZbJ79Rz2bvGsHx49BJ8HtJj0YnpZbnox7z5njn4PlpWhr2XAJmNnctrQ8ES0Qvrop/AQ== dependencies: - "@parcel/plugin" "^2.0.0-alpha.3.1" + "@parcel/plugin" "2.0.0-beta.1" -"@parcel/packager-ts@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/packager-ts/-/packager-ts-2.0.0-alpha.3.1.tgz#c50235d919050fbfaa121578116c4bdbf7109e89" - integrity sha512-tasZk+79dfwiHdgIec6XWiiDM0+Bc1sndtAcplvzbPbFkgViZZZjGu3103uC/giUbCZd+P8mwgt4I+aFjc1yDA== +"@parcel/packager-ts@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/packager-ts/-/packager-ts-2.0.0-beta.1.tgz#20e5f8449ff60ccee3999741cad6bd33d96bdfb9" + integrity sha512-x/sOSvIVV6z7ltG1XFuJ/Da72HAHkRxNLCzE2ggEnuB9kzOWXAlIHKeeGB2Ql3lV2OOMtoQoFg4BM1nBLJzFCg== dependencies: - "@parcel/plugin" "^2.0.0-alpha.3.1" + "@parcel/plugin" "2.0.0-beta.1" -"@parcel/plugin@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/plugin/-/plugin-2.0.0-alpha.3.1.tgz#cf0aa095ff6831ebfb722eea5395c867cad36928" - integrity sha512-Wbo4dXtVRZXP1S9Scii46fE6MeHvZjw6eS7/WLhiapvsthWjXQlljLfbjA5ih+6poQv7jgJLUlwZDPxKcHmH8Q== +"@parcel/plugin@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/plugin/-/plugin-2.0.0-beta.1.tgz#b19f571f59a4f979cc1310d3e0d073fbd9988bd2" + integrity sha512-ik8kwNTJ7wfPRWHQK5NrUat3WGOZazIv8v1Lbgew6XuVTc333FitvBn6mxpPWp2N3+GWWrVGmBG8m7MI6kB8zw== dependencies: - "@parcel/types" "^2.0.0-alpha.3.1" + "@parcel/types" "2.0.0-beta.1" -"@parcel/reporter-cli@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/reporter-cli/-/reporter-cli-2.0.0-alpha.3.1.tgz#596fbd2ccf92472443795a950d6d5e8a5426b9c3" - integrity sha512-pdqlksBEuL6FPa+q5Y9jcQH2csxWUNzf8NDK42RnGNRPWnXfJHviErrvCidscaCbFWlgO/LOjyFQ0QxrqbBtjA== +"@parcel/reporter-bundle-analyzer@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/reporter-bundle-analyzer/-/reporter-bundle-analyzer-2.0.0-beta.1.tgz#98b39a6cc56792d48e83e7ec88b176adb133e600" + integrity sha512-igUEsMSgyIiAEvmjdIydcmYpTFUKQB5EAtbMEYvRWlCSEGR08EZqaY58SIiTaTUv4maQuAi0k7E3QQSDeBtQ/w== dependencies: - "@parcel/events" "^2.0.0-alpha.3.1" - "@parcel/plugin" "^2.0.0-alpha.3.1" - "@parcel/types" "^2.0.0-alpha.3.1" - "@parcel/utils" "^2.0.0-alpha.3.1" - cli-spinners "^2.0.0" + "@parcel/plugin" "2.0.0-beta.1" + "@parcel/utils" "2.0.0-beta.1" + nullthrows "^1.1.1" + +"@parcel/reporter-bundle-buddy@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/reporter-bundle-buddy/-/reporter-bundle-buddy-2.0.0-beta.1.tgz#7f01ab7d37dc214380e25a1d8572f6074fe3fa49" + integrity sha512-pW7SJFKGkkjOOYYcE20BgleC1DRswM04fZ82S9NS0idnEsJ1Z+z/QCww24J1Vfx5FGEQDVOl4siHNILm04kvdg== + dependencies: + "@parcel/plugin" "2.0.0-beta.1" + +"@parcel/reporter-cli@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/reporter-cli/-/reporter-cli-2.0.0-beta.1.tgz#ba0effb57f1ac397275e16e76b51f29d8f2bd179" + integrity sha512-KmyfFhClXghMxZXbS8tkoXZZqVfuLzlUDwedMAN+Jr9h8vSZYaiqjq88mNdrLIubqLepbNG7jUcXPu/Y3ynz6Q== + dependencies: + "@parcel/plugin" "2.0.0-beta.1" + "@parcel/types" "2.0.0-beta.1" + "@parcel/utils" "2.0.0-beta.1" + chalk "^3.0.0" filesize "^3.6.0" - grapheme-breaker "^0.3.2" - ink "^2.1.1" - ink-spinner "^3.0.1" nullthrows "^1.1.1" - react "^16.7.0" + ora "^4.0.3" + string-width "^4.2.0" + strip-ansi "^6.0.0" + term-size "^2.1.1" -"@parcel/reporter-dev-server@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/reporter-dev-server/-/reporter-dev-server-2.0.0-alpha.3.1.tgz#751feb2d1821aefc39b4e3ade59d40b4b9a58191" - integrity sha512-orZD40KB6aMqBGaX4TibICMeSgGsGsMUnOMjPAGUlYpW3Z50cu4H/bPcJELVsOQTcRsEnW+f4SX7e1qNUM2+oQ== +"@parcel/reporter-dev-server@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/reporter-dev-server/-/reporter-dev-server-2.0.0-beta.1.tgz#6040b4d2da7d65a238775f51a39ec6f5d7ac5ddf" + integrity sha512-84u4lfwAqGrIrbuyTYq88PckSe1mKP+f+D5aQDObWBqDy1gSokM+yKnQQHoddQAhviyTY3tJU/SEvKSp0Dog9Q== dependencies: - "@parcel/plugin" "^2.0.0-alpha.3.1" - "@parcel/utils" "^2.0.0-alpha.3.1" + "@parcel/plugin" "2.0.0-beta.1" + "@parcel/utils" "2.0.0-beta.1" connect "^3.7.0" ejs "^2.6.1" http-proxy-middleware "^0.19.1" mime "^2.4.4" - -"@parcel/reporter-hmr-server@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/reporter-hmr-server/-/reporter-hmr-server-2.0.0-alpha.3.1.tgz#e420be15ab7e5e4ad1c59cd0286801ae408b54ee" - integrity sha512-14JfRPwIOo5viexaZwJqNbrtW6ZC4abmcA6bnTdAPkQQkIuaR01vxyToCU2ZZp9m+grg/9KXBukyC9HIQuqd4A== - dependencies: - "@parcel/plugin" "^2.0.0-alpha.3.1" - "@parcel/reporter-cli" "^2.0.0-alpha.3.1" - "@parcel/utils" "^2.0.0-alpha.3.1" + nullthrows "^1.1.1" ws "^6.2.0" -"@parcel/resolver-default@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/resolver-default/-/resolver-default-2.0.0-alpha.3.1.tgz#d77efc9de06e3d5419848ab8d5e71ac5c7b4783e" - integrity sha512-/m/PicKKalGyYuUh6kgornk6X59gZNtNYPrjFhW2LVlr0+UxrK/QmreI/6GoIrrOfoIQCmz9e9tM2Yh/M22wjg== +"@parcel/resolver-default@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/resolver-default/-/resolver-default-2.0.0-beta.1.tgz#eb3349339a18c5d8aa3c01d8813d14640e7f45b7" + integrity sha512-BnnHY83oqOIk3oK7QsJbB2QdtSIWVy948JI7bhfFC0+8zWMLifE28KTZQD1JGxICOre75DK1JRN26l8F1gtuiw== dependencies: - "@parcel/plugin" "^2.0.0-alpha.3.1" - "@parcel/utils" "^2.0.0-alpha.3.1" - micromatch "^3.0.4" - node-libs-browser "^2.1.0" + "@parcel/node-resolver-core" "2.0.0-beta.1" + "@parcel/plugin" "2.0.0-beta.1" -"@parcel/runtime-browser-hmr@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/runtime-browser-hmr/-/runtime-browser-hmr-2.0.0-alpha.3.1.tgz#b372d809777f5c76b2f44c16b706e4fb495fe18a" - integrity sha512-NPmxw+nLnx1boTwJdPMXYXYumb8GXk423Xo2uZaf7VL95gr+CZf7nod1kDn2XEQYgWDFCrNKR5BqcoSX32fnYw== +"@parcel/runtime-browser-hmr@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/runtime-browser-hmr/-/runtime-browser-hmr-2.0.0-beta.1.tgz#6c0e85e13c10cc1f0d91c4d0ae8e45bf954f1ed7" + integrity sha512-5JQGDLwqAGk0kNqlgKPA99mPN8srpabu/2drpxSBKWXDA71v47JRYcGx8gQsvdZGgj3+rrkI2nyC8UlYAM+m+w== dependencies: - "@parcel/plugin" "^2.0.0-alpha.3.1" - "@parcel/utils" "^2.0.0-alpha.3.1" + "@parcel/plugin" "2.0.0-beta.1" + "@parcel/utils" "2.0.0-beta.1" -"@parcel/runtime-js@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/runtime-js/-/runtime-js-2.0.0-alpha.3.1.tgz#298ce01e0ac3d590170c8189bb0e4387fee66046" - integrity sha512-Q2v2auDNEiLs5Vmdv3u4lBgN+PrpvbAUzi6U1SG65UhDIUWL1Z1qumBctwXV92PoQoi3wwzR1BtV/ErN3cJoJQ== +"@parcel/runtime-js@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/runtime-js/-/runtime-js-2.0.0-beta.1.tgz#12a370afad5333b03d5b237ee96c74553e95a743" + integrity sha512-1EHrOoNzCdksj4QfLuIr5rC8rO8FsVpQdl4ZLggMsxQV67wFiG9j1KwM/+Jmpd6dsmdkSW+b/NAC5kPXnE1EfQ== dependencies: - "@parcel/plugin" "^2.0.0-alpha.3.1" - "@parcel/utils" "^2.0.0-alpha.3.1" + "@parcel/plugin" "2.0.0-beta.1" + "@parcel/utils" "2.0.0-beta.1" nullthrows "^1.1.1" -"@parcel/runtime-react-refresh@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/runtime-react-refresh/-/runtime-react-refresh-2.0.0-alpha.3.1.tgz#0514efdc7721990d86e053db064aa7a26e867ee1" - integrity sha512-ZT5s/laZSSEjCywiXBxuRzMluWpk8k/gjk3wx0FHYK6Win2Lbi/ViKuOAM4qmNKKSMUZUJPQKfdNMc+Jv3miOg== +"@parcel/runtime-react-refresh@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/runtime-react-refresh/-/runtime-react-refresh-2.0.0-beta.1.tgz#eeb6c0179149b69e51b29cb5f02e59d93706aca6" + integrity sha512-d7lShNcgyKAdrDwAqNzVeOeQ7MuqtElw4YPxHAmTrJnsr8k+scPmK7IiUSPqItuvLIngpS1IoLY1SuEAQAY/QA== dependencies: - "@parcel/plugin" "^2.0.0-alpha.3.1" + "@parcel/plugin" "2.0.0-beta.1" react-refresh "^0.6.0" -"@parcel/scope-hoisting@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/scope-hoisting/-/scope-hoisting-2.0.0-alpha.3.1.tgz#60e0387a416acca780b9c53496303c0ff46f9efe" - integrity sha512-GFdBGxUNDLQcQ+jAm+hp+Zn9faxvfY7qnmd3pCAHGgn6MHC8THJ8VSM0E6MobG8G5Qi6iYU0y+YvQ6rjrNiulw== +"@parcel/scope-hoisting@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/scope-hoisting/-/scope-hoisting-2.0.0-beta.1.tgz#7013c831c2880491c000325c1d6233c76088c5fc" + integrity sha512-U0ZcejwG6vMj+cLHScQ7lhPWaaXgNk+xGPu6adWNQVbRB3PqJMv6jIhBwgR2afWzNwu1a3vg1aRO9DH/jpxGdg== dependencies: "@babel/generator" "^7.3.3" "@babel/parser" "^7.0.0" "@babel/template" "^7.2.2" "@babel/traverse" "^7.2.3" "@babel/types" "^7.3.3" - "@parcel/utils" "^2.0.0-alpha.3.1" - babylon-walk "^1.0.2" + "@parcel/babylon-walk" "2.0.0-beta.1" + "@parcel/diagnostic" "2.0.0-beta.1" + "@parcel/source-map" "2.0.0-alpha.4.13" + "@parcel/utils" "2.0.0-beta.1" nullthrows "^1.1.1" -"@parcel/source-map@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/source-map/-/source-map-2.0.0-alpha.3.1.tgz#f47af787afb3a8917145ef838c55e93e462e675e" - integrity sha512-3aL1UwzeJUKryXKvUkSiiVGd2vS6tjqInbQTundEmoOY103uzE4Pyg3RiSRzAFbz+H7CJHnhz/aQdaykGO9IJg== +"@parcel/source-map@2.0.0-alpha.4.13": + version "2.0.0-alpha.4.13" + resolved "https://registry.yarnpkg.com/@parcel/source-map/-/source-map-2.0.0-alpha.4.13.tgz#2b262be6e99a15e9de3f6656df27c0b0c4809b83" + integrity sha512-MnIfYmaRqnwK8kRRG9Osu1DkJGl2bVSfJs9SqauJ9N4dOdAXAFGeeDtzXnHvx02DO+HwK7YjsbhBpSvvgZcWHg== dependencies: - "@parcel/utils" "^2.0.0-alpha.3.1" - nullthrows "^1.1.1" - source-map "^0.7.3" + node-addon-api "^2.0.0" + node-gyp-build "^4.2.2" -"@parcel/transformer-babel@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/transformer-babel/-/transformer-babel-2.0.0-alpha.3.1.tgz#d962ef4608833e33943198a2126ba34aa3c174b4" - integrity sha512-9NM6huhWNz9i2G32WiP0hzrrUbiLbMDiOnjeTXe+++F0b+WFLvSa7F0AWPcolrElGZoRjXj3tieHgF01gqiZNA== +"@parcel/transformer-babel@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/transformer-babel/-/transformer-babel-2.0.0-beta.1.tgz#9233185441391258d664c9241352f66a2395452e" + integrity sha512-nP8TsjhYYvL5NjRX6WNZFXjcY66fwrPthslnycNldoHpmRDoRO1PFjqx1zzJJEUc1S0r6M2kTQhDuh4dXhANCA== dependencies: "@babel/core" "^7.0.0" "@babel/generator" "^7.0.0" + "@babel/helper-compilation-targets" "^7.8.4" "@babel/plugin-transform-flow-strip-types" "^7.0.0" - "@babel/plugin-transform-react-jsx" "^7.0.0" "@babel/plugin-transform-typescript" "^7.4.5" "@babel/preset-env" "^7.0.0" + "@babel/preset-react" "^7.0.0" "@babel/traverse" "^7.0.0" - "@parcel/babel-preset-env" "^2.0.0-alpha.3.1" - "@parcel/plugin" "^2.0.0-alpha.3.1" - "@parcel/source-map" "^2.0.0-alpha.3.1" - "@parcel/utils" "^2.0.0-alpha.3.1" + "@parcel/babel-ast-utils" "2.0.0-beta.1" + "@parcel/babel-preset-env" "2.0.0-beta.1" + "@parcel/plugin" "2.0.0-beta.1" + "@parcel/utils" "2.0.0-beta.1" browserslist "^4.6.6" core-js "^3.2.1" nullthrows "^1.1.1" - semver "^5.4.1" + semver "^5.7.0" -"@parcel/transformer-coffeescript@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/transformer-coffeescript/-/transformer-coffeescript-2.0.0-alpha.3.1.tgz#076af4afbeee1f15dfb2dac3059ba55b1ac9211c" - integrity sha512-S6hUsEeeztojZk4Rj7tuWHdOwY7zDWqxF22A3GiRkuDmqC1rGtnZ2snfYiCnC4UAoqB69QkaFpZBdpNltxwz3g== +"@parcel/transformer-coffeescript@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/transformer-coffeescript/-/transformer-coffeescript-2.0.0-beta.1.tgz#b399b95620e71d62738fb510f68454ce0962a614" + integrity sha512-EP0+RAGrMIGoIG3g3VdjAIkMCfFj8gnVp8e8n61nzrnqE7pmF8KuGtGAYz6U8yQb39a1OF41sEg1huvOUT3nKw== dependencies: - "@parcel/plugin" "^2.0.0-alpha.3.1" - "@parcel/source-map" "^2.0.0-alpha.3.1" - "@parcel/utils" "^2.0.0-alpha.3.1" + "@parcel/plugin" "2.0.0-beta.1" + "@parcel/source-map" "2.0.0-alpha.4.13" + "@parcel/utils" "2.0.0-beta.1" coffeescript "^2.0.3" nullthrows "^1.1.1" semver "^5.4.1" -"@parcel/transformer-css@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/transformer-css/-/transformer-css-2.0.0-alpha.3.1.tgz#dec0378c39490dfbd6fc49a7a036eb22e35941dc" - integrity sha512-oJ3N0acB0O6WQxfwI2D+yjviCm1j3YE7UDULrpqAKciiz65zTt8lMYRinXf9q+grsOcYqEUrosPFlqU5tf1whQ== +"@parcel/transformer-css@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/transformer-css/-/transformer-css-2.0.0-beta.1.tgz#68899a329695dde4115ab44a1a7c08d38c99157d" + integrity sha512-+vRvTWeQNxzRfsv9A9gGXYt6p6NU6LcyLvByIMzwDhqsMq1wsIEmw+YPM/2TzqsKI/f+B0jkTNCMI2dQobFX0g== dependencies: - "@parcel/plugin" "^2.0.0-alpha.3.1" + "@parcel/plugin" "2.0.0-beta.1" + "@parcel/source-map" "2.0.0-alpha.4.13" + "@parcel/utils" "2.0.0-beta.1" postcss "^7.0.5" postcss-value-parser "^3.3.1" semver "^5.4.1" -"@parcel/transformer-graphql@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/transformer-graphql/-/transformer-graphql-2.0.0-alpha.3.1.tgz#c941d8ab223503ea22b7bd108bb8ab6292bb5e0a" - integrity sha512-E1TDgOaL3FV1FqTZ7TsSVScq98nZAjShjM0+SNdJ3Aw3dvN4REIZgzO9qcSufkefS4OOTHfrKXp/r2VhUtHjPw== +"@parcel/transformer-graphql@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/transformer-graphql/-/transformer-graphql-2.0.0-beta.1.tgz#7c1dc7718c9dc33ce65c3f0e36a9306f85e8e395" + integrity sha512-IYuSUHadoEn5plZx78fZr8ViGdU2GqbY0opkGP21i1Z0TiB4h0ON9VMbEgnABAGeR1b+9rly/8e9/isOC7jcow== dependencies: - "@parcel/plugin" "^2.0.0-alpha.3.1" + "@parcel/plugin" "2.0.0-beta.1" -"@parcel/transformer-html@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/transformer-html/-/transformer-html-2.0.0-alpha.3.1.tgz#cfa913692f8abb8ad52f653b2733e1d8d3df23fe" - integrity sha512-FYDeL6iFB0+1EZpM0GTyOo/B2vCNfjEp1Y8X7OOCnuQBuVTW8fb1XI8mFa0RoSfgBx+1vIdaIILQa+qGPvHxtw== +"@parcel/transformer-html@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/transformer-html/-/transformer-html-2.0.0-beta.1.tgz#e30e9f08add69afc9c82d9e748ae554dd6701074" + integrity sha512-YkwNLKsMrNzyA4u1I8OvTxhYAfkAayP+rDGxcIuTOmv4IVZGoRCWMtYqUl40xdIVE0QmJpbkAuQtG7Vn3xOlHw== dependencies: - "@parcel/plugin" "^2.0.0-alpha.3.1" - "@parcel/utils" "^2.0.0-alpha.3.1" + "@parcel/plugin" "2.0.0-beta.1" + "@parcel/utils" "2.0.0-beta.1" nullthrows "^1.1.1" posthtml "^0.11.3" posthtml-parser "^0.4.1" posthtml-render "^1.1.5" semver "^5.4.1" -"@parcel/transformer-inline-string@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/transformer-inline-string/-/transformer-inline-string-2.0.0-alpha.3.1.tgz#e41611a9079a053bc8f69abf7982305d1a8281ed" - integrity sha512-NKWm1zEcj3Qq8nna+bSjruwVIlBaNgain5wCPmSRCviFs8KCPNqu0zOiSk6135Gr9fluzGpzefD3eINwlrAyCg== +"@parcel/transformer-inline-string@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/transformer-inline-string/-/transformer-inline-string-2.0.0-beta.1.tgz#306deba7dff779c7e450136839f51064c6cb1672" + integrity sha512-XfhPAXWvrWQSOwHGQU3koP6vs85mcjyKllVGcC24/Io2nZhzACw6br0fzZL2gSVZeEt+/TtfxVu7uA44S8tA8g== dependencies: - "@parcel/plugin" "^2.0.0-alpha.3.1" + "@parcel/plugin" "2.0.0-beta.1" -"@parcel/transformer-js@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/transformer-js/-/transformer-js-2.0.0-alpha.3.1.tgz#6aea570445ef303824e318d4c916d9739cb4834a" - integrity sha512-9N5p0V/c/gdvXDOMCuCAcYWLGVwjFEBQ31rw3gPNnJyQePZ4icwv2bC8tWJK4V3gynlcTek9hRRHhq69QCNGew== +"@parcel/transformer-js@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/transformer-js/-/transformer-js-2.0.0-beta.1.tgz#350e41f2536d55eb69cc8628b918c5a31d1ce70c" + integrity sha512-60rrUF+ApahxKc1eQizyo7umvOhIRe3sxRIYub61qRPan2S7aU7PbScZ4bboh3alQYLztTNQh2VazM85oyiQSw== dependencies: "@babel/core" "^7.0.0" "@babel/generator" "^7.0.0" @@ -2395,167 +3277,186 @@ "@babel/template" "^7.0.0" "@babel/traverse" "^7.0.0" "@babel/types" "^7.0.0" - "@parcel/plugin" "^2.0.0-alpha.3.1" - "@parcel/scope-hoisting" "^2.0.0-alpha.3.1" - "@parcel/source-map" "^2.0.0-alpha.3.1" - "@parcel/utils" "^2.0.0-alpha.3.1" - babylon-walk "^1.0.2" - node-libs-browser "^2.0.0" + "@parcel/babel-ast-utils" "2.0.0-beta.1" + "@parcel/babylon-walk" "2.0.0-beta.1" + "@parcel/diagnostic" "2.0.0-beta.1" + "@parcel/plugin" "2.0.0-beta.1" + "@parcel/scope-hoisting" "2.0.0-beta.1" + "@parcel/utils" "2.0.0-beta.1" nullthrows "^1.1.1" semver "^5.4.1" -"@parcel/transformer-json@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/transformer-json/-/transformer-json-2.0.0-alpha.3.1.tgz#dc9d05d59da3158cd63cd5c1137f530378472b46" - integrity sha512-laF4vTyxxdU9ONASbGfWHIy+FoofZMjc0yaJ52SilOdDEa+eIG/UGnetEmml8VsIJStlYH/Qhz3C2XMY2zk/UQ== +"@parcel/transformer-json@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/transformer-json/-/transformer-json-2.0.0-beta.1.tgz#c1519d3ca166d223d185fca1fab9fc32fd4e618f" + integrity sha512-v39TaEWgJnoOqOQGtZgZBAq3dihufqeSm9+szIxzm4FiwzOzzlyo9QiLSlCfjDbuWHFvQkU5AJKSlhdS2qbN3Q== dependencies: - "@parcel/plugin" "^2.0.0-alpha.3.1" + "@parcel/plugin" "2.0.0-beta.1" json5 "^2.1.0" -"@parcel/transformer-less@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/transformer-less/-/transformer-less-2.0.0-alpha.3.1.tgz#8a9e29832685621d6cc376d2e566ed21ec3fff1a" - integrity sha512-nsLobEm7uy2YVMWC8hxi1J9IWniJ/UcJMdXfAMy5wQa/1acK4HFpc2xdQhT07sb88HL2qDnqvDEA6Rqs/GYNdQ== +"@parcel/transformer-jsonld@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/transformer-jsonld/-/transformer-jsonld-2.0.0-beta.1.tgz#ccff5e330ba82a137e4166e8538b9f5dd921c778" + integrity sha512-rf1n90XjrYDCD4jZ3+z+acQm4hznOe2l2Os3aVLCs1jvf6TAXMOtkHN1ABh63GAON5LJsary3YdFNrullDRTFw== + dependencies: + "@parcel/plugin" "2.0.0-beta.1" + "@parcel/types" "2.0.0-beta.1" + json5 "^2.1.2" + +"@parcel/transformer-less@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/transformer-less/-/transformer-less-2.0.0-beta.1.tgz#09e58220404781f406e9241a1ea859f19a91adc5" + integrity sha512-jKi29fKEJW4R1e0Rwo2nTfEeIA11vdMs3tHOhkq1O3lfkmK9UF98uFlweLyfF8Mm7XznEqKL7aP58drJ8UqVuQ== dependencies: - "@parcel/plugin" "^2.0.0-alpha.3.1" + "@parcel/plugin" "2.0.0-beta.1" + "@parcel/source-map" "2.0.0-alpha.4.13" -"@parcel/transformer-postcss@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/transformer-postcss/-/transformer-postcss-2.0.0-alpha.3.1.tgz#a364cb2b1aae4a04419a225ba4a236c3f78b9808" - integrity sha512-ZxUSCBpIXVdK+r7lT6w5nDyvsqic8xRRaM6DthXrRQVV3pQA3YzHFlCV343UY/Hn+N+2AocmG1GrZHi2EP6pyg== +"@parcel/transformer-mdx@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/transformer-mdx/-/transformer-mdx-2.0.0-beta.1.tgz#139057e1acedb2b6eeb5472e60f3853d20ab4760" + integrity sha512-M4Jjws7n5at/AVMiITz6KIMZMzlF7WHuhfQ+YzAqXS2Z+f0mJ/c2/XNOSVrKbcjn+9aKoSYqwq6vmJ6wUSaBXQ== dependencies: - "@parcel/plugin" "^2.0.0-alpha.3.1" - "@parcel/utils" "^2.0.0-alpha.3.1" + "@parcel/plugin" "2.0.0-beta.1" + +"@parcel/transformer-postcss@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/transformer-postcss/-/transformer-postcss-2.0.0-beta.1.tgz#15f8802730d6d2ba21ef044119d6394657e248ab" + integrity sha512-RLJcK5rsNv7wzehZfqR9w4lBXF+OKeza57HJ7KGph6bBtwTsLedlioQakU7uXFWprbZE6NUa2ZDIxUhWmP9kQA== + dependencies: + "@parcel/plugin" "2.0.0-beta.1" + "@parcel/utils" "2.0.0-beta.1" css-modules-loader-core "^1.1.0" nullthrows "^1.1.1" postcss "^7.0.5" postcss-value-parser "^3.3.1" semver "^5.4.1" -"@parcel/transformer-posthtml@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/transformer-posthtml/-/transformer-posthtml-2.0.0-alpha.3.1.tgz#5557657256529ec00097d1d1250843ee2f9d8ec2" - integrity sha512-v+MFsFY1hS8pjaIwWJDrleEmoPMWdBbzuAkcK3M1b2dVEw+dMihdFIZPccFVS+dN6h27x2N0Zg+kLUOSQczHMg== +"@parcel/transformer-posthtml@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/transformer-posthtml/-/transformer-posthtml-2.0.0-beta.1.tgz#db1b1b5b96203225cb05916b6091c3bb69e3ef2c" + integrity sha512-dUbB3dB57qtjqmf00VeZIQRNnbEVOLCGchTIQXOoa1Ys0YqcEHNOAP7yU/njykQtxIBNp41CRXkvLl+4M6egyQ== dependencies: - "@parcel/plugin" "^2.0.0-alpha.3.1" + "@parcel/plugin" "2.0.0-beta.1" nullthrows "^1.1.1" posthtml "^0.11.3" posthtml-parser "^0.4.1" posthtml-render "^1.1.5" semver "^5.4.1" -"@parcel/transformer-pug@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/transformer-pug/-/transformer-pug-2.0.0-alpha.3.1.tgz#7a7073e175d20fff3d25e563f60682cc85e62ce6" - integrity sha512-xq6yqzllQuySxkdep7UF75TDIMryiRmP1+0Dksbyjx8X8hmEBbV45TKBoGqzsKkxTeAxPumT4vgqVq/3Mhfv2A== +"@parcel/transformer-pug@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/transformer-pug/-/transformer-pug-2.0.0-beta.1.tgz#45ffdb02d17fa3bbfcbb8acf07a28d30734d8175" + integrity sha512-o6jXARg1HuEetLdKRn6EuJ5YGFbql3mAtK+D/Tj5/DDg1RIlBK4Cih3Gi/lyCjHF7a7Woc0mKP09cA95va5ZUA== dependencies: - "@parcel/plugin" "^2.0.0-alpha.3.1" + "@parcel/plugin" "2.0.0-beta.1" -"@parcel/transformer-raw@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/transformer-raw/-/transformer-raw-2.0.0-alpha.3.1.tgz#dc5cfdf6e97fd6041cade4e0d2f970d30c39ec89" - integrity sha512-Mh13nyQ+NgQLRbuikxM1NK5Qf5Kk3MaWjDyetY0N+QAtiKVhJF7fYCtRpMpo5z+zRBClq8sLHFMAn61YVZWy6w== +"@parcel/transformer-raw@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/transformer-raw/-/transformer-raw-2.0.0-beta.1.tgz#7a46974e08b1a45bb633e3e14cdceafd53f37c08" + integrity sha512-SLqd5KBH7k8Gh25MMUTdR6tdWWWTVKuQNF76uOzysIpdbQX/ix7v12wmyeSOxivrc1eDUtILkLUH0e9HIxWVvw== dependencies: - "@parcel/plugin" "^2.0.0-alpha.3.1" + "@parcel/plugin" "2.0.0-beta.1" -"@parcel/transformer-react-refresh-babel@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/transformer-react-refresh-babel/-/transformer-react-refresh-babel-2.0.0-alpha.3.1.tgz#86293b7e35e8433ad67e819aa1555c4ffa6f9667" - integrity sha512-d6WeHpGk5zP29g/iKZ+Zf7sZq1XEA6VJ52GXDiY1uh82fVm2x4BHx+j2YBOPXhsKlyi7fBQXTUrxGP623jfZVw== +"@parcel/transformer-react-refresh-babel@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/transformer-react-refresh-babel/-/transformer-react-refresh-babel-2.0.0-beta.1.tgz#ed327591e50d5e2f4b29c8b3b74af1774caecfdb" + integrity sha512-DlsjjujHGgmSEsazN9Ng/0Q7dMSATB7kxAe7CADE+Y8cf8kBmSeeuFokbnxTGg3TBeGMjeeHcOhXwXwNeHkEQQ== dependencies: - "@parcel/plugin" "^2.0.0-alpha.3.1" + "@parcel/plugin" "2.0.0-beta.1" react-refresh "^0.6.0" -"@parcel/transformer-react-refresh-wrap@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/transformer-react-refresh-wrap/-/transformer-react-refresh-wrap-2.0.0-alpha.3.1.tgz#c21a095616c12861517a4e6e92ae65c2adb2ac98" - integrity sha512-SMSuWlh2J1mZG5yhG+//sRxuf9wSF2XJfmh8FIiFPkE5KdSnngEI5vcDxUpvzEb7eo6Jjzmz0+80rfeUhOmpMg== +"@parcel/transformer-react-refresh-wrap@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/transformer-react-refresh-wrap/-/transformer-react-refresh-wrap-2.0.0-beta.1.tgz#e10dcf29e4859a4423a272133fc3f4f5f5d1d963" + integrity sha512-PJiCdXGQgd3Z2zVs1KLie9sU5kagtMMWNVHomJ9QeG4tnvoG/J4P4klJRLO218GqBnB/s4u8vNH0QbGuQO98HQ== dependencies: "@babel/generator" "^7.0.0" "@babel/parser" "^7.0.0" "@babel/template" "^7.0.0" "@babel/types" "^7.0.0" - "@parcel/plugin" "^2.0.0-alpha.3.1" - "@parcel/source-map" "^2.0.0-alpha.3.1" - "@parcel/utils" "^2.0.0-alpha.3.1" + "@parcel/babel-ast-utils" "2.0.0-beta.1" + "@parcel/plugin" "2.0.0-beta.1" + "@parcel/utils" "2.0.0-beta.1" react-refresh "^0.6.0" semver "^5.4.1" -"@parcel/transformer-sass@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/transformer-sass/-/transformer-sass-2.0.0-alpha.3.1.tgz#bab1209ada685d2290570886e53c7e13adf7f8e6" - integrity sha512-ZElQMiV/Fi4vWQsUNUlfuuK7t+YR7f/ISUvYmKUii5vmnskq4a6UwWqWLT5OuscPk4Zc/QeNctkI33YFAOH3XQ== +"@parcel/transformer-sass@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/transformer-sass/-/transformer-sass-2.0.0-beta.1.tgz#848888573ee10f131ac2a1e8495b503236f9dda6" + integrity sha512-E5sPsmtmvqsB90YEbDD7VFQ5o6+t97YQD35aIZnsZHkuI9MhFEaVHROtzeq3n3nuZ6tjyr6rv2SseZj1yculzg== dependencies: - "@parcel/fs" "^2.0.0-alpha.3.1" - "@parcel/plugin" "^2.0.0-alpha.3.1" - "@parcel/utils" "^2.0.0-alpha.3.1" + "@parcel/fs" "2.0.0-beta.1" + "@parcel/plugin" "2.0.0-beta.1" + "@parcel/source-map" "2.0.0-alpha.4.13" + "@parcel/utils" "2.0.0-beta.1" -"@parcel/transformer-stylus@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/transformer-stylus/-/transformer-stylus-2.0.0-alpha.3.1.tgz#5ea4c1fddfa7d63c9c77d47477c9cc53a2c9c471" - integrity sha512-QYyvDESfk6KuPv5qG4M+MdBSrONLYMjbDsHkBF9pMATy3WLyFD2bfwv7eVVHwFnp/zuRnuHy7h2GU9zk//y5tA== +"@parcel/transformer-stylus@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/transformer-stylus/-/transformer-stylus-2.0.0-beta.1.tgz#5ee55a080cad210f3d7ba0c086caba4c85821b93" + integrity sha512-mTh4f59XVxM7vHRP183Cp+0bVOZ0/eyOWQrFBKBt27ZbJvLy2ynxFed/goYpjz8QT+ZJsjmPYViKLxrSdHaQTQ== dependencies: - "@parcel/plugin" "^2.0.0-alpha.3.1" - "@parcel/utils" "^2.0.0-alpha.3.1" + "@parcel/plugin" "2.0.0-beta.1" + "@parcel/utils" "2.0.0-beta.1" -"@parcel/transformer-sugarss@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/transformer-sugarss/-/transformer-sugarss-2.0.0-alpha.3.1.tgz#e12caf92d7ae4d1979ad24bc22c77f4f959abb7e" - integrity sha512-E2I2pBHmALE6Bbu6/X4lfuP3a0JWeLmaJRxtWlVNjWVQwyRIKeEuuUZ70wwl9Gydhv9mBmgDuS9jyPxsCDo3dQ== +"@parcel/transformer-sugarss@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/transformer-sugarss/-/transformer-sugarss-2.0.0-beta.1.tgz#61e8b20a83bf0746c5a28c942cb588a7e1980fe5" + integrity sha512-73B7XDAZg0qymhlOEYhI4o8vdUbrm0ZUl/mqzXn13WsgstTtkwJPS8bX/QbyEnFq4xg/ktyezhmhNYLd+GAzjA== dependencies: - "@parcel/plugin" "^2.0.0-alpha.3.1" + "@parcel/plugin" "2.0.0-beta.1" postcss "^7.0.5" -"@parcel/transformer-toml@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/transformer-toml/-/transformer-toml-2.0.0-alpha.3.1.tgz#74e54596c90629882dc3b5bc873f87d986b02539" - integrity sha512-hkOhaUIVvghKuo7pyU3gUYZ+8kJk+lfrIFnbYujwqzys9m0WhAQGELc2syb9IYrD7zVZaeI0hB5cJpnHUodBLQ== +"@parcel/transformer-toml@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/transformer-toml/-/transformer-toml-2.0.0-beta.1.tgz#6dc28dfb0e47be6bf9ea387e19034b8b3d4290dd" + integrity sha512-EHVS83evOcLJB2wvxQkZCWNjOAYaKg9qfnkbtvEztzx228KcQWg4IPiJgB6+dcBC5fuMBYIw0xZ24y3/3ZkPfg== dependencies: - "@parcel/plugin" "^2.0.0-alpha.3.1" + "@parcel/plugin" "2.0.0-beta.1" -"@parcel/transformer-typescript-types@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/transformer-typescript-types/-/transformer-typescript-types-2.0.0-alpha.3.1.tgz#41b9db71b144f174da3ccd7687eaf02cf36555be" - integrity sha512-duMzWnq49AOSUU9W18GvdycPw/DSfOzKZcY/znYE65eSmEYgcNgWGI6TaluY52FA0cfgLakUe013KmGGI9tyjA== +"@parcel/transformer-typescript-types@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/transformer-typescript-types/-/transformer-typescript-types-2.0.0-beta.1.tgz#6275cefb72e248e93619d03692952fc5841476d3" + integrity sha512-QVCe66C14zAsss71wso32OHo74aquVDyYfqO0a/+E62bTA2O8tLaeJ9dwMHgVRgw0tBobh/j6AKaOTeQFLqobA== dependencies: - "@parcel/plugin" "^2.0.0-alpha.3.1" - "@parcel/source-map" "^2.0.0-alpha.3.1" - "@parcel/ts-utils" "^2.0.0-alpha.3.1" + "@parcel/plugin" "2.0.0-beta.1" + "@parcel/source-map" "2.0.0-alpha.4.13" + "@parcel/ts-utils" "2.0.0-beta.1" nullthrows "^1.1.1" -"@parcel/transformer-yaml@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/transformer-yaml/-/transformer-yaml-2.0.0-alpha.3.1.tgz#90f73de36273b3da066381b0dccd7df5f183aa2f" - integrity sha512-sX+8B111x9q1+BgCPq2w08+nfSvXJ/ijdC+YkpqbKeWkcmHDfXI8esajKWW6xSaeaX6UgNfoZopDCsqUWBAxLA== +"@parcel/transformer-yaml@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/transformer-yaml/-/transformer-yaml-2.0.0-beta.1.tgz#f725c1d6d6b3f1e9fec77b6ee1fe6768fc3c3a53" + integrity sha512-/pe59NOi6rtbE+YQEnOdxgNf5zMd5SXHnawICGa1Gn9rXDFswiKzD16O2meCy0VGF6dPsQdzL+k0PJlQd9/TDA== dependencies: - "@parcel/plugin" "^2.0.0-alpha.3.1" + "@parcel/plugin" "2.0.0-beta.1" -"@parcel/ts-utils@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/ts-utils/-/ts-utils-2.0.0-alpha.3.1.tgz#4d40a7ca8615e90fb8af2b514cfdbd65d3ad25af" - integrity sha512-AaafmGAtiBDtO9Ly3ZvyQViF1FCjHFe97QzIC1HShBmQrzD918LZTH7vAnUjUIDYuudn9Gq/26PfQdPM5dYGzA== +"@parcel/ts-utils@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/ts-utils/-/ts-utils-2.0.0-beta.1.tgz#bd2da0134e994ec5058acf60383122956178df6b" + integrity sha512-lSw4fWL/PLsJruTmScQRVvtw2g75jsd55W08GuMdkr9iGIOXxTRZ4m4rdDBVsiS6Cgq2/l2M3zPnTiPX2do2kw== dependencies: nullthrows "^1.1.1" -"@parcel/types@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/types/-/types-2.0.0-alpha.3.1.tgz#f73a8a242b6cd820f7c8aa6a0629c505314b5bc0" - integrity sha512-+RrfckMkA9BQtR/O987gwD/1fXWeMd5v8k4pBBsmSHtLh7ASnoViRkg9drIQJs6uU17uKgvYNsSYwUNxJzf+0Q== +"@parcel/types@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/types/-/types-2.0.0-beta.1.tgz#c5581aa754c342a1e5ef382f2bf20555923b672a" + integrity sha512-2aB5MoEyNUXb34IG1YVRiC5HTHgqWAX8/mM+JGAUit/kTb7eRVtnQtOhQHWyGyLqkEwbLrLo3s272sp5LNK90A== -"@parcel/utils@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/utils/-/utils-2.0.0-alpha.3.1.tgz#837f68666640c118bd57ac0a4ccea72c9976d815" - integrity sha512-8j3Sbp3J2ahR/MZREwVYYPEvf3LDjFkb1ZA2bq3PljWc+evDNt0ofunP1fBH9w/GvJEtPSx4bu1Z8mINTA/d4Q== +"@parcel/utils@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/utils/-/utils-2.0.0-beta.1.tgz#885fc328aaab049ef6ccebdb71236f4f013377ee" + integrity sha512-o+qTRMqe6QjdseYKZBGTOjnxRt4bIOEfH5ey9Ohl5fRGIfuWH7Tsq3fUkf/McvoAQyR6eo1vp7OrPBUQeQ6wxw== dependencies: "@iarna/toml" "^2.2.0" - "@parcel/codeframe" "^2.0.0-alpha.3.1" - "@parcel/diagnostic" "^2.0.0-alpha.3.1" - "@parcel/logger" "^2.0.0-alpha.3.1" - "@parcel/markdown-ansi" "^2.0.0-alpha.3.1" + "@parcel/codeframe" "2.0.0-beta.1" + "@parcel/diagnostic" "2.0.0-beta.1" + "@parcel/logger" "2.0.0-beta.1" + "@parcel/markdown-ansi" "2.0.0-beta.1" + "@parcel/source-map" "2.0.0-alpha.4.13" ansi-html "^0.0.7" + chalk "^2.4.2" clone "^2.1.1" - deasync "^0.1.14" - fast-glob "^3.0.4" + fast-glob "3.1.1" is-glob "^4.0.0" is-url "^1.2.2" js-levenshtein "^1.1.6" @@ -2563,30 +3464,30 @@ micromatch "^4.0.2" node-forge "^0.8.1" nullthrows "^1.1.1" + open "^7.0.3" resolve "^1.12.0" - serialize-to-js "^1.1.1" + serialize-to-js "^3.0.1" terser "^3.7.3" -"@parcel/watcher@^2.0.0-alpha.4": - version "2.0.0-alpha.4" - resolved "https://registry.yarnpkg.com/@parcel/watcher/-/watcher-2.0.0-alpha.4.tgz#d2c88ed7945c00373ab984bfb39b2394f882b794" - integrity sha512-J8Detm6Yeh27lNVr02/bTxqQ5dAs040C9OB1Zs7C4kaDCq/Dx7FVph0aRKDhAiZ0BiSBwgZEh7xmD4ZU844kxA== +"@parcel/watcher@^2.0.0-alpha.5": + version "2.0.0-alpha.7" + resolved "https://registry.yarnpkg.com/@parcel/watcher/-/watcher-2.0.0-alpha.7.tgz#377f273adde0655c29b46d6249a08c0fa06dcfc5" + integrity sha512-ry+kXaOe22YV1UV5Wnv99Hb+gyjjljOYOaSN1Nc5qHL83SxKhawivI8pKSqoaCSlE8aRnIz8NQ0x7pABUyIpng== dependencies: - bindings "^1.5.0" - node-addon-api "^1.6.2" - prebuild-install "^5.2.5" + lint-staged "^10.0.8" + node-addon-api "^3.0.0" + node-gyp-build "^4.2.1" -"@parcel/workers@^2.0.0-alpha.3.1": - version "2.0.0-alpha.3.1" - resolved "https://registry.yarnpkg.com/@parcel/workers/-/workers-2.0.0-alpha.3.1.tgz#c93d58ea6fee0ee809c88a2976d67c71e1a0d540" - integrity sha512-XJqRQ5sCFoDFsCupJcUugTOp2RCtrlDuuwyDj9z3migsZ7tDxGhch/ewOy8qePk++aBEIgsNvn0hiERQHK5/0g== +"@parcel/workers@2.0.0-beta.1": + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@parcel/workers/-/workers-2.0.0-beta.1.tgz#9a57544479862ce886c1b8280bc31c7bc6b467ab" + integrity sha512-8ycDNpBM9WoRVsHB+QXA/Y4I3z18vOQVFY+/vIcLNDIr61zKETwPjOmr5+6wSa6cMWaZBXYUjm2heJ6bPi1QXg== dependencies: - "@parcel/diagnostic" "^2.0.0-alpha.3.1" - "@parcel/logger" "^2.0.0-alpha.3.1" - "@parcel/utils" "^2.0.0-alpha.3.1" + "@parcel/diagnostic" "2.0.0-beta.1" + "@parcel/logger" "2.0.0-beta.1" + "@parcel/utils" "2.0.0-beta.1" chrome-trace-event "^1.0.2" nullthrows "^1.1.1" - physical-cpu-count "^2.0.0" "@sinonjs/commons@^1.7.0": version "1.8.0" @@ -2790,11 +3691,6 @@ abab@^2.0.0, abab@^2.0.3: resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.3.tgz#623e2075e02eb2d3f2475e49f99c91846467907a" integrity sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg== -abbrev@1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" - integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== - abortcontroller-polyfill@^1.1.9: version "1.4.0" resolved "https://registry.yarnpkg.com/abortcontroller-polyfill/-/abortcontroller-polyfill-1.4.0.tgz#0d5eb58e522a461774af8086414f68e1dda7a6c4" @@ -2831,11 +3727,6 @@ acorn-walk@^7.1.1: resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== -acorn@^5.0.0: - version "5.7.3" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" - integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== - acorn@^6.0.1, acorn@^6.0.4: version "6.4.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.0.tgz#b659d2ffbafa24baf5db1cdbb2c94a983ecd2784" @@ -2846,6 +3737,14 @@ acorn@^7.1.1, acorn@^7.2.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.3.1.tgz#85010754db53c3fbaf3b9ea3e083aa5c5d147ffd" integrity sha512-tLc0wSnatxAQHVHUapaHdz72pi9KUyHjq5KyHjGg9Y8Ifdc79pTh2XvI6I1/chZbnM7QtNKzh66ooDogPZSleA== +aggregate-error@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.0.1.tgz#db2fe7246e536f40d9b5442a39e117d7dd6a24e0" + integrity sha512-quoaXsZ9/BLNae5yiNoUz+Nhkwz83GhWwtYFglcjEQB2NDHCIpApbqXxIFnm4Pq/Nvhrsq5sYJFyohrrxnTGAA== + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" + ajv@^6.10.0, ajv@^6.10.2: version "6.12.2" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.2.tgz#c629c5eced17baf314437918d2da88c99d5958cd" @@ -2876,11 +3775,6 @@ ansi-colors@^3.2.1: resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf" integrity sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA== -ansi-escapes@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" - integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== - ansi-escapes@^4.2.1: version "4.3.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.0.tgz#a4ce2b33d6b214b7950d8595c212f12ac9cc569d" @@ -2888,6 +3782,13 @@ ansi-escapes@^4.2.1: dependencies: type-fest "^0.8.1" +ansi-escapes@^4.3.0: + version "4.3.1" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.1.tgz#a5c47cc43181f1f38ffd7076837700d395522a61" + integrity sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA== + dependencies: + type-fest "^0.11.0" + ansi-html@^0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/ansi-html/-/ansi-html-0.0.7.tgz#813584021962a9e9e6fd039f940d12f56ca7859e" @@ -2898,11 +3799,6 @@ ansi-regex@^2.0.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= -ansi-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= - ansi-regex@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" @@ -2949,19 +3845,6 @@ anymatch@^3.0.3: normalize-path "^3.0.0" picomatch "^2.0.4" -aproba@^1.0.3: - version "1.2.0" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" - integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== - -are-we-there-yet@~1.1.2: - version "1.1.5" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" - integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== - dependencies: - delegates "^1.0.0" - readable-stream "^2.0.6" - argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -3002,6 +3885,11 @@ array-equal@^1.0.0: resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93" integrity sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM= +array-filter@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-1.0.0.tgz#baf79e62e6ef4c2a4c0b831232daffec251f9d83" + integrity sha1-uveeYubvTCpMC4MSMtr/7CUfnYM= + array-includes@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.1.tgz#cdd67e6852bdf9c1215460786732255ed2459348" @@ -3016,11 +3904,6 @@ array-unique@^0.3.2: resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= -arrify@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" - integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug== - asn1.js@^4.0.0: version "4.10.1" resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" @@ -3042,13 +3925,15 @@ assert-plus@1.0.0, assert-plus@^1.0.0: resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= -assert@^1.1.1: - version "1.5.0" - resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb" - integrity sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA== +assert@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/assert/-/assert-2.0.0.tgz#95fc1c616d48713510680f2eaf2d10dd22e02d32" + integrity sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A== dependencies: - object-assign "^4.1.1" - util "0.10.3" + es6-object-assign "^1.1.0" + is-nan "^1.2.1" + object-is "^1.0.1" + util "^0.12.0" assign-symbols@^1.0.0: version "1.0.0" @@ -3080,10 +3965,12 @@ atob@^2.1.2: resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== -auto-bind@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/auto-bind/-/auto-bind-3.0.0.tgz#67773e64899b228f6d2a841709e7e086cfed31a3" - integrity sha512-v0A231a/lfOo6kxQtmEkdBfTApvC21aJYukA8pkKnoTvVqh3Wmm7/Rwy4GBCHTTHVoLVA5qsBDDvf1XY1nIV2g== +available-typed-arrays@^1.0.0, available-typed-arrays@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.2.tgz#6b098ca9d8039079ee3f77f7b783c4480ba513f5" + integrity sha512-XWX3OX8Onv97LMk/ftVyBibpGwY5a8SmuxZPzeOxqmuEqUCOM9ZE+uIaD1VNJ5QnvU2UQusvmKbuM1FR8QWGfQ== + dependencies: + array-filter "^1.0.0" aws-sign2@~0.7.0: version "0.7.0" @@ -3215,33 +4102,6 @@ babel-preset-react-app@^9.1.2: babel-plugin-macros "2.8.0" babel-plugin-transform-react-remove-prop-types "0.4.24" -babel-runtime@^6.11.6, babel-runtime@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" - integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= - dependencies: - core-js "^2.4.0" - regenerator-runtime "^0.11.0" - -babel-types@^6.15.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" - integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc= - dependencies: - babel-runtime "^6.26.0" - esutils "^2.0.2" - lodash "^4.17.4" - to-fast-properties "^1.0.3" - -babylon-walk@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/babylon-walk/-/babylon-walk-1.0.2.tgz#3b15a5ddbb482a78b4ce9c01c8ba181702d9d6ce" - integrity sha1-OxWl3btIKni0zpwByLoYFwLZ1s4= - dependencies: - babel-runtime "^6.11.6" - babel-types "^6.15.0" - lodash.clone "^4.5.0" - balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" @@ -3277,20 +4137,6 @@ big.js@^5.2.2: resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== -bindings@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" - integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== - dependencies: - file-uri-to-path "1.0.0" - -bl@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/bl/-/bl-3.0.0.tgz#3611ec00579fd18561754360b21e9f784500ff88" - integrity sha512-EUAyP5UHU5hxF8BPT0LKW8gjYLhq1DQIcneOX/pL/m2Alo+OYDQAJlHq+yseMP50Os2nHXOSic6Ss3vSQeyf4A== - dependencies: - readable-stream "^3.0.1" - bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0: version "4.11.8" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" @@ -3332,16 +4178,6 @@ braces@^3.0.1: dependencies: fill-range "^7.0.1" -brfs@^1.2.0: - version "1.6.1" - resolved "https://registry.yarnpkg.com/brfs/-/brfs-1.6.1.tgz#b78ce2336d818e25eea04a0947cba6d4fb8849c3" - integrity sha512-OfZpABRQQf+Xsmju8XE9bDjs+uU4vLREGolP7bDgcpsI17QREyZ4Bl+2KLxxx1kCgA0fAIhKQBaBYh+PEcCqYQ== - dependencies: - quote-stream "^1.0.1" - resolve "^1.1.5" - static-module "^2.2.0" - through2 "^2.0.0" - brorand@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" @@ -3442,11 +4278,6 @@ bser@2.1.1: dependencies: node-int64 "^0.4.0" -buffer-equal@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-0.0.1.tgz#91bc74b11ea405bc916bc6aa908faafa5b4aac4b" - integrity sha1-kbx0sR6kBbyRa8aqkI+q+ltKrEs= - buffer-from@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" @@ -3457,14 +4288,13 @@ buffer-xor@^1.0.3: resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= -buffer@^4.3.0: - version "4.9.2" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8" - integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg== +buffer@^5.5.0: + version "5.6.0" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.6.0.tgz#a31749dc7d81d84db08abf937b6b8c4033f62786" + integrity sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw== dependencies: base64-js "^1.0.2" ieee754 "^1.1.4" - isarray "^1.0.0" builtin-status-codes@^3.0.0: version "3.0.0" @@ -3593,11 +4423,6 @@ char-regex@^1.0.2: resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== -chownr@^1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.3.tgz#42d837d5239688d55f303003a508230fa6727142" - integrity sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw== - chrome-trace-event@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz#234090ee97c7d4ad1a2c4beae27505deffc608a4" @@ -3628,12 +4453,10 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" -cli-cursor@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" - integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU= - dependencies: - restore-cursor "^2.0.0" +clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== cli-cursor@^3.1.0: version "3.1.0" @@ -3642,17 +4465,12 @@ cli-cursor@^3.1.0: dependencies: restore-cursor "^3.1.0" -cli-spinners@^1.0.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-1.3.1.tgz#002c1990912d0d59580c93bd36c056de99e4259a" - integrity sha512-1QL4544moEsDVH9T/l6Cemov/37iv1RtoKf7NJ04A60+4MREXNfx/QvavbH6QoGdsD4N4Mwy49cmaINR/o2mdg== - -cli-spinners@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.2.0.tgz#e8b988d9206c692302d8ee834e7a85c0144d8f77" - integrity sha512-tgU3fKwzYjiLEQgPMD9Jt+JjHVL9kW93FiIMX/l7rivvOD4/LL0Mf7gda3+4U2KJBloybwgj5KEoQgGRioMiKQ== +cli-spinners@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.3.0.tgz#0632239a4b5aa4c958610142c34bb7a651fc8df5" + integrity sha512-Xs2Hf2nzrvJMFKimOR7YR0QwZ8fc0u98kdtwN1eNAZzNQgH3vK2pXzff6GJtKh7S5hoJ87ECiAiZFS2fb5Ii2w== -cli-truncate@^2.0.0: +cli-truncate@2.1.0, cli-truncate@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-2.1.0.tgz#c39e28bf05edcde5be3b98992a22deed5a2b93c7" integrity sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg== @@ -3683,16 +4501,16 @@ cliui@^6.0.0: strip-ansi "^6.0.0" wrap-ansi "^6.2.0" +clone@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" + integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= + clone@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= -clones@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/clones/-/clones-1.2.0.tgz#b34c872045446a9f264ccceb7731bca05c529b71" - integrity sha512-FXDYw4TjR8wgPZYui2LeTqWh1BLpfQ8lB6upMtlpDF6WlOOxghmTTxWyngdKTgozqBgKnHbTVwTE+hOHqAykuQ== - co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" @@ -3707,11 +4525,6 @@ coa@^2.0.2: chalk "^2.4.1" q "^1.1.2" -code-point-at@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= - coffeescript@^2.0.3: version "2.5.0" resolved "https://registry.yarnpkg.com/coffeescript/-/coffeescript-2.5.0.tgz#9ce853766fa8363384d80f06f79fa8d5b13f566f" @@ -3787,6 +4600,11 @@ commander@^2.19.0, commander@^2.20.0: resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== +commander@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae" + integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg== + component-emitter@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" @@ -3797,24 +4615,6 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= -concat-stream@~1.6.0: - version "1.6.2" - resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" - integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== - dependencies: - buffer-from "^1.0.0" - inherits "^2.0.3" - readable-stream "^2.2.2" - typedarray "^0.0.6" - -config-chain@^1.1.12: - version "1.1.12" - resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa" - integrity sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA== - dependencies: - ini "^1.3.4" - proto-list "~1.2.1" - confusing-browser-globals@^1.0.9: version "1.0.9" resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.9.tgz#72bc13b483c0276801681871d4898516f8f54fdd" @@ -3830,22 +4630,17 @@ connect@^3.7.0: parseurl "~1.3.3" utils-merge "1.0.1" -console-browserify@^1.1.0: +console-browserify@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== -console-control-strings@^1.0.0, console-control-strings@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= - constants-browserify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= -convert-source-map@^1.4.0, convert-source-map@^1.5.1, convert-source-map@^1.6.0, convert-source-map@^1.7.0: +convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== @@ -3878,11 +4673,6 @@ core-js-pure@^3.0.0: resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.6.5.tgz#c79e75f5e38dbc85a662d91eea52b8256d53b813" integrity sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA== -core-js@^2.4.0: - version "2.6.11" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c" - integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg== - core-js@^3.2.1: version "3.6.2" resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.2.tgz#2799ea1a59050f0acf50dfe89b916d6503b16caa" @@ -3965,7 +4755,7 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.2: shebang-command "^2.0.0" which "^2.0.1" -crypto-browserify@^3.11.0: +crypto-browserify@^3.12.0: version "3.12.0" resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== @@ -4208,14 +4998,6 @@ data-urls@^2.0.0: whatwg-mimetype "^2.3.0" whatwg-url "^8.0.0" -deasync@^0.1.14: - version "0.1.19" - resolved "https://registry.yarnpkg.com/deasync/-/deasync-0.1.19.tgz#e7ea89fcc9ad483367e8a48fe78f508ca86286e8" - integrity sha512-oh3MRktfnPlLysCPpBpKZZzb4cUC/p0aA3SyRGp15lN30juJBTo/CiD0d4fR+f1kBtUQoJj1NE9RPNWQ7BQ9Mg== - dependencies: - bindings "^1.5.0" - node-addon-api "^1.7.1" - debug@2.6.9, debug@^2.2.0, debug@^2.3.3: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -4252,17 +5034,10 @@ decode-uri-component@^0.2.0: resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= -decompress-response@^4.2.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-4.2.1.tgz#414023cc7a302da25ce2ec82d0d5238ccafd8986" - integrity sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw== - dependencies: - mimic-response "^2.0.0" - -deep-extend@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== +dedent@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" + integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw= deep-is@^0.1.3, deep-is@~0.1.3: version "0.1.3" @@ -4274,6 +5049,13 @@ deepmerge@^4.2.2: resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== +defaults@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" + integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730= + dependencies: + clone "^1.0.2" + define-properties@^1.1.2, define-properties@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" @@ -4308,11 +5090,6 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= -delegates@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= - des.js@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" @@ -4321,11 +5098,6 @@ des.js@^1.0.0: inherits "^2.0.1" minimalistic-assert "^1.0.0" -detect-libc@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" - integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= - detect-newline@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" @@ -4377,10 +5149,10 @@ dom-serializer@0: domelementtype "^2.0.1" entities "^2.0.0" -domain-browser@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" - integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== +domain-browser@^3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-3.5.0.tgz#3a11f5df52fd9d60d7f1c79a62fde2d158c42b09" + integrity sha512-zrzUu6auyZWRexjCEPJnfWc30Hupxh2lJZOJAF3qa2bCuD4O/55t0FvQt3ZMhEw++gjNkwdkOVZh8yA32w/Vfw== domelementtype@1, domelementtype@^1.3.1: version "1.3.1" @@ -4438,13 +5210,6 @@ dotenv@^7.0.0: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-7.0.0.tgz#a2be3cd52736673206e8a85fb5210eea29628e7c" integrity sha512-M3NhsLbV1i6HuGzBUH8vXrtxOk+tWmzWKDMbAVSUp3Zsjm7ywFeuwrUXhmhQyRK1q5B5GGy7hcXPbj3bnfZg2g== -duplexer2@~0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1" - integrity sha1-ixLauHjA1p4+eJEFFmKjL8a93ME= - dependencies: - readable-stream "^2.0.2" - ecc-jsbn@~0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" @@ -4453,16 +5218,6 @@ ecc-jsbn@~0.1.1: jsbn "~0.1.0" safer-buffer "^2.1.0" -editorconfig@^0.15.3: - version "0.15.3" - resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-0.15.3.tgz#bef84c4e75fb8dcb0ce5cee8efd51c15999befc5" - integrity sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g== - dependencies: - commander "^2.19.0" - lru-cache "^4.1.5" - semver "^5.6.0" - sigmund "^1.0.1" - ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" @@ -4525,7 +5280,7 @@ encodeurl@~1.0.2: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= -end-of-stream@^1.1.0, end-of-stream@^1.4.1: +end-of-stream@^1.1.0: version "1.4.4" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== @@ -4556,7 +5311,7 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.17.0, es-abstract@^1.17.5: +es-abstract@^1.17.0, es-abstract@^1.17.4, es-abstract@^1.17.5: version "1.17.6" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.6.tgz#9142071707857b2cacc7b89ecb670316c3e2d52a" integrity sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw== @@ -4599,6 +5354,11 @@ es-to-primitive@^1.2.1: is-date-object "^1.0.1" is-symbol "^1.0.2" +es6-object-assign@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/es6-object-assign/-/es6-object-assign-1.1.0.tgz#c2c3582656247c39ea107cb1e6652b6f9f24523c" + integrity sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw= + escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" @@ -4614,7 +5374,7 @@ escape-string-regexp@^2.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== -escodegen@^1.11.0, escodegen@^1.11.1: +escodegen@^1.11.0: version "1.12.1" resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.12.1.tgz#08770602a74ac34c7a90ca9229e7d51e379abc76" integrity sha512-Q8t2YZ+0e0pc7NRVj3B4tSQ9rim1oi4Fh46k2xhJ2qOiEwhQfdjyEQddWdj7ZFaKmU+5104vn1qrcjEPWq+bgQ== @@ -4638,18 +5398,6 @@ escodegen@^1.14.1: optionalDependencies: source-map "~0.6.1" -escodegen@~1.9.0: - version "1.9.1" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.9.1.tgz#dbae17ef96c8e4bedb1356f4504fa4cc2f7cb7e2" - integrity sha512-6hTjO1NAWkHnDk3OqQ4YrCuwwmGHL9S3nPlzBOUG/R44rda3wLNrfvQ5fkSGjyhHFKM7ALPKcKGrwvCLe0lC7Q== - dependencies: - esprima "^3.1.3" - estraverse "^4.2.0" - esutils "^2.0.2" - optionator "^0.8.1" - optionalDependencies: - source-map "~0.6.1" - eslint-config-fbjs@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/eslint-config-fbjs/-/eslint-config-fbjs-1.1.1.tgz#dd29f8d912e8a755257e9eeef00bae1cce57f73a" @@ -4816,7 +5564,7 @@ estraverse@^5.1.0: resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.1.0.tgz#374309d39fd935ae500e7b92e8a6b4c720e59642" integrity sha512-FyohXK+R0vE+y1nHLoBM7ZTyqRpqAlhdZHCWIWEviFLiGB8b04H6bQs8G+XTthacvT8VuwvteiP7RJSxMs8UEw== -esutils@^2.0.0, esutils@^2.0.2: +esutils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== @@ -4826,10 +5574,10 @@ eventemitter3@^4.0.0: resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.0.tgz#d65176163887ee59f386d64c82610b696a4a74eb" integrity sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg== -events@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/events/-/events-3.0.0.tgz#9a0a0dfaf62893d92b875b8f2698ca4114973e88" - integrity sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA== +events@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.1.0.tgz#84279af1b34cb75aa88bf5ff291f6d0bd9b31a59" + integrity sha512-Rv+u8MLHNOdMjTAFeT3nCjHn2aGlx435FP/sDHNaRhDEMwyI/aB22Kj2qIN8R0cw3z28psEQLYwxVKLsKrMgWg== evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: version "1.0.3" @@ -4872,6 +5620,21 @@ execa@^4.0.0: signal-exit "^3.0.2" strip-final-newline "^2.0.0" +execa@^4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/execa/-/execa-4.0.3.tgz#0a34dabbad6d66100bd6f2c576c8669403f317f2" + integrity sha512-WFDXGHckXPWZX19t1kCsXzOpqX9LWYNqn4C+HqZlk/V0imTkzJZqf87ZBhvpHaftERYknpk0fjSylnXVlVgI0A== + dependencies: + cross-spawn "^7.0.0" + get-stream "^5.0.0" + human-signals "^1.1.1" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.0" + onetime "^5.1.0" + signal-exit "^3.0.2" + strip-final-newline "^2.0.0" + exit@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" @@ -4890,11 +5653,6 @@ expand-brackets@^2.1.4: snapdragon "^0.8.1" to-regex "^3.0.1" -expand-template@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c" - integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg== - expect@^26.0.1: version "26.0.1" resolved "https://registry.yarnpkg.com/expect/-/expect-26.0.1.tgz#18697b9611a7e2725e20ba3ceadda49bc9865421" @@ -4951,16 +5709,6 @@ extsprintf@^1.2.0: resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= -falafel@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/falafel/-/falafel-2.1.0.tgz#96bb17761daba94f46d001738b3cedf3a67fe06c" - integrity sha1-lrsXdh2rqU9G0AFzizzt86Z/4Gw= - dependencies: - acorn "^5.0.0" - foreach "^2.0.5" - isarray "0.0.1" - object-keys "^1.0.6" - fast-deep-equal@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" @@ -4971,7 +5719,7 @@ fast-deep-equal@^3.1.1: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-glob@^3.0.4: +fast-glob@3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.1.1.tgz#87ee30e9e9f3eb40d6f254a7997655da753d7c82" integrity sha512-nTCREpBY8w8r+boyFYAx21iL6faSsQynliPHM4Uf56SbkyohCNxpVPEH9xrF5TXKy+IsjkPUHDKiUkzBVRXn9g== @@ -5018,6 +5766,13 @@ fb-watchman@^2.0.0: dependencies: bser "2.1.1" +figures@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" + integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== + dependencies: + escape-string-regexp "^1.0.5" + file-entry-cache@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" @@ -5025,11 +5780,6 @@ file-entry-cache@^5.0.1: dependencies: flat-cache "^2.0.1" -file-uri-to-path@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" - integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== - filesize@^3.6.0: version "3.6.1" resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.6.1.tgz#090bb3ee01b6f801a8a8be99d31710b3422bb317" @@ -5101,10 +5851,10 @@ flatted@^2.0.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== -flow-bin@^0.127.0: - version "0.127.0" - resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.127.0.tgz#0614cff4c1b783beef1feeb7108d536e09d77632" - integrity sha512-ywvCCdV4NJWzrqjFrMU5tAiVGyBiXjsJQ1+/kj8thXyX15V17x8BFvNwoAH97NrUU8T1HzmFBjLzWc0l2319qg== +flow-bin@^0.128.0: + version "0.128.0" + resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.128.0.tgz#fd1232a64dc46874d8d499f16a1934b964f4c2ae" + integrity sha512-EnmMSOCrkx8F0r1+T1d1HODQ+ddy5yRfkT3CvwmK05IWZyXQy27OVdNwdXUWRqc0iMW75T4QkoXaVBYrMqfk+A== follow-redirects@^1.0.0: version "1.9.0" @@ -5149,11 +5899,6 @@ fragment-cache@^0.2.1: dependencies: map-cache "^0.2.2" -fs-constants@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" - integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== - fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -5174,20 +5919,6 @@ functional-red-black-tree@^1.0.1: resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= -gauge@~2.7.3: - version "2.7.4" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= - dependencies: - aproba "^1.0.3" - console-control-strings "^1.0.0" - has-unicode "^2.0.0" - object-assign "^4.1.0" - signal-exit "^3.0.0" - string-width "^1.0.1" - strip-ansi "^3.0.1" - wide-align "^1.1.0" - generic-names@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/generic-names/-/generic-names-2.0.1.tgz#f8a378ead2ccaa7a34f0317b05554832ae41b872" @@ -5205,6 +5936,11 @@ get-caller-file@^2.0.1: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== +get-own-enumerable-property-symbols@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664" + integrity sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g== + get-package-type@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" @@ -5246,11 +5982,6 @@ getpass@^0.1.1: dependencies: assert-plus "^1.0.0" -github-from-package@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" - integrity sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4= - glob-parent@^5.0.0: version "5.1.1" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" @@ -5289,19 +6020,11 @@ globals@^12.1.0: dependencies: type-fest "^0.8.1" -graceful-fs@^4.2.4: +graceful-fs@^4.1.2, graceful-fs@^4.2.4: version "4.2.4" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== -grapheme-breaker@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/grapheme-breaker/-/grapheme-breaker-0.3.2.tgz#5b9e6b78c3832452d2ba2bb1cb830f96276410ac" - integrity sha1-W55reMODJFLSuiuxy4MPlidkEKw= - dependencies: - brfs "^1.2.0" - unicode-trie "^0.3.1" - growly@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" @@ -5352,11 +6075,6 @@ has-symbols@^1.0.0, has-symbols@^1.0.1: resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== -has-unicode@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= - has-value@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" @@ -5388,7 +6106,7 @@ has-values@^1.0.0: is-number "^3.0.0" kind-of "^4.0.0" -has@^1.0.0, has@^1.0.1, has@^1.0.3: +has@^1.0.0, has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== @@ -5562,6 +6280,11 @@ ieee754@^1.1.4: resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg== +iferr@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/iferr/-/iferr-1.0.2.tgz#e9fde49a9da06dc4a4194c6c9ed6d08305037a6d" + integrity sha512-9AfeLfji44r5TKInjhz3W9DyZI1zR1JAf2hVBMGhddAKPqBsupb89jGfbCTHIGZd6fGZl9WlHdn4AObygyMKwg== + ignore@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" @@ -5614,58 +6337,11 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3: +inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== -inherits@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" - integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= - -inherits@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= - -ini@^1.3.4, ini@~1.3.0: - version "1.3.5" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" - integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== - -ink-spinner@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/ink-spinner/-/ink-spinner-3.0.1.tgz#7b4b206d2b18538701fd92593f9acabbfe308dce" - integrity sha512-AVR4Z/NXDQ7dT5ltWcCzFS9Dd4T8eaO//E2UO8VYNiJcZpPCSJ11o5A0UVPcMlZxGbGD6ikUFDR3ZgPUQk5haQ== - dependencies: - cli-spinners "^1.0.0" - prop-types "^15.5.10" - -ink@^2.1.1: - version "2.6.0" - resolved "https://registry.yarnpkg.com/ink/-/ink-2.6.0.tgz#04acefbed32f6ef9ed20512c51ec8b8e09a890c5" - integrity sha512-nD/wlSuB6WnFsFB0nUcOJdy28YvvDer3eo+gezjvZqojGA4Rx5sQpacvN//Aai83DRgwrRTyKBl5aciOcfP3zQ== - dependencies: - ansi-escapes "^4.2.1" - arrify "^2.0.1" - auto-bind "^3.0.0" - chalk "^3.0.0" - cli-cursor "^3.1.0" - cli-truncate "^2.0.0" - is-ci "^2.0.0" - lodash.throttle "^4.1.1" - log-update "^3.0.0" - prop-types "^15.6.2" - react-reconciler "^0.24.0" - scheduler "^0.18.0" - signal-exit "^3.0.2" - slice-ansi "^3.0.0" - string-length "^3.1.0" - widest-line "^3.1.0" - wrap-ansi "^6.2.0" - yoga-layout-prebuilt "^1.9.3" - internal-slot@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.2.tgz#9c2e9fb3cd8e5e4256c6f45fe310067fcfa378a3" @@ -5711,6 +6387,11 @@ is-accessor-descriptor@^1.0.0: dependencies: kind-of "^6.0.0" +is-arguments@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.0.4.tgz#3faf966c7cba0ff437fb31f6250082fcf0448cf3" + integrity sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA== + is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" @@ -5819,13 +6500,6 @@ is-extglob@^2.1.1: resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= -is-fullwidth-code-point@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= - dependencies: - number-is-nan "^1.0.0" - is-fullwidth-code-point@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" @@ -5841,6 +6515,11 @@ is-generator-fn@^2.0.0: resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== +is-generator-function@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.7.tgz#d2132e529bb0000a7f80794d4bdf5cd5e5813522" + integrity sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw== + is-glob@^4.0.0, is-glob@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" @@ -5855,6 +6534,18 @@ is-html@^1.1.0: dependencies: html-tags "^1.0.0" +is-interactive@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" + integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== + +is-nan@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.3.0.tgz#85d1f5482f7051c2019f5673ccebdb06f3b0db03" + integrity sha512-z7bbREymOqt2CCaZVly8aC4ML3Xhfi0ekuOnjO2L8vKdl+CttdVoGZQhd4adMFAsxQ5VeRVwORs4tU8RH+HFtQ== + dependencies: + define-properties "^1.1.3" + is-number@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" @@ -5867,7 +6558,7 @@ is-number@^7.0.0: resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== -is-obj@^1.0.0: +is-obj@^1.0.0, is-obj@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= @@ -5898,6 +6589,11 @@ is-regex@^1.1.0: dependencies: has-symbols "^1.0.1" +is-regexp@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" + integrity sha1-/S2INUXEa6xaYz57mgnof6LLUGk= + is-resolvable@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" @@ -5932,6 +6628,16 @@ is-symbol@^1.0.2: dependencies: has-symbols "^1.0.1" +is-typed-array@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.3.tgz#a4ff5a5e672e1a55f99c7f54e59597af5c1df04d" + integrity sha512-BSYUBOK/HJibQ30wWkWold5txYwMUXQct9YHAQJr8fSwvZoiglcqB0pd7vEN23+Tsi9IUEjztdOSzl4qLVYGTQ== + dependencies: + available-typed-arrays "^1.0.0" + es-abstract "^1.17.4" + foreach "^2.0.5" + has-symbols "^1.0.1" + is-typedarray@^1.0.0, is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" @@ -5959,12 +6665,7 @@ is-wsl@^2.1.1: dependencies: is-docker "^2.0.0" -isarray@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= - -isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: +isarray@1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= @@ -6422,17 +7123,6 @@ jest@^26.0.1: import-local "^3.0.2" jest-cli "^26.0.1" -js-beautify@^1.8.9: - version "1.10.2" - resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.10.2.tgz#88c9099cd6559402b124cfab18754936f8a7b178" - integrity sha512-ZtBYyNUYJIsBWERnQP0rPN9KjkrDfJcMjuVGcvXOUJrD1zmOGwhRwQ4msG+HJ+Ni/FA7+sRQEMYVzdTQDvnzvQ== - dependencies: - config-chain "^1.1.12" - editorconfig "^0.15.3" - glob "^7.1.3" - mkdirp "~0.5.1" - nopt "~4.0.1" - js-levenshtein@^1.1.3, js-levenshtein@^1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d" @@ -6661,6 +7351,41 @@ lines-and-columns@^1.1.6: resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= +lint-staged@^10.0.8: + version "10.2.11" + resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-10.2.11.tgz#713c80877f2dc8b609b05bc59020234e766c9720" + integrity sha512-LRRrSogzbixYaZItE2APaS4l2eJMjjf5MbclRZpLJtcQJShcvUzKXsNeZgsLIZ0H0+fg2tL4B59fU9wHIHtFIA== + dependencies: + chalk "^4.0.0" + cli-truncate "2.1.0" + commander "^5.1.0" + cosmiconfig "^6.0.0" + debug "^4.1.1" + dedent "^0.7.0" + enquirer "^2.3.5" + execa "^4.0.1" + listr2 "^2.1.0" + log-symbols "^4.0.0" + micromatch "^4.0.2" + normalize-path "^3.0.0" + please-upgrade-node "^3.2.0" + string-argv "0.3.1" + stringify-object "^3.3.0" + +listr2@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/listr2/-/listr2-2.2.0.tgz#cb88631258abc578c7fb64e590fe5742f28e4aac" + integrity sha512-Q8qbd7rgmEwDo1nSyHaWQeztfGsdL6rb4uh7BA+Q80AZiDET5rVntiU1+13mu2ZTDVaBVbvAD1Db11rnu3l9sg== + dependencies: + chalk "^4.0.0" + cli-truncate "^2.1.0" + figures "^3.2.0" + indent-string "^4.0.0" + log-update "^4.0.0" + p-map "^4.0.0" + rxjs "^6.5.5" + through "^2.3.8" + loader-utils@^1.1.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" @@ -6718,29 +7443,39 @@ lodash.sortby@^4.7.0: resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= -lodash.throttle@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" - integrity sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ= - lodash.uniq@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4: +lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== -log-update@^3.0.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/log-update/-/log-update-3.3.0.tgz#3b0501815123f66cb33f300e3dac2a2b6ad3fdf5" - integrity sha512-YSKm5n+YjZoGZT5lfmOqasVH1fIH9xQA9A81Y48nZ99PxAP62vdCCtua+Gcu6oTn0nqtZd/LwRV+Vflo53ZDWA== +log-symbols@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-3.0.0.tgz#f3a08516a5dea893336a7dee14d18a1cfdab77c4" + integrity sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ== + dependencies: + chalk "^2.4.2" + +log-symbols@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.0.0.tgz#69b3cc46d20f448eccdb75ea1fa733d9e821c920" + integrity sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA== + dependencies: + chalk "^4.0.0" + +log-update@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/log-update/-/log-update-4.0.0.tgz#589ecd352471f2a1c0c570287543a64dfd20e0a1" + integrity sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg== dependencies: - ansi-escapes "^3.2.0" - cli-cursor "^2.1.0" - wrap-ansi "^5.0.0" + ansi-escapes "^4.3.0" + cli-cursor "^3.1.0" + slice-ansi "^4.0.0" + wrap-ansi "^6.2.0" loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: version "1.4.0" @@ -6757,21 +7492,6 @@ lowlight@~1.9.0: fault "^1.0.2" highlight.js "~9.12.0" -lru-cache@^4.1.5: - version "4.1.5" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" - integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== - dependencies: - pseudomap "^1.0.2" - yallist "^2.1.2" - -magic-string@^0.22.4: - version "0.22.5" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.22.5.tgz#8e9cf5afddf44385c1da5bc2a6a0dbd10b03657e" - integrity sha512-oreip9rJZkzvA8Qzk9HFs8fZGF/u7H/gtrE8EN6RjKJ9kh2HlC+yQ2QezifqTZfGyiuAV0dRv5a+y/8gBb1m9w== - dependencies: - vlq "^0.2.2" - make-dir@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" @@ -6817,13 +7537,6 @@ memoize-one@^5.1.1: resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.1.1.tgz#047b6e3199b508eaec03504de71229b8eb1d75c0" integrity sha512-HKeeBpWvqiVJD57ZUAsJNm71eHTykffzcLZVYWiVfQeI1rJtuEaS7hQiEpWfVVk18donPwJEcFKIkCmPJNOhHA== -merge-source-map@1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/merge-source-map/-/merge-source-map-1.0.4.tgz#a5de46538dae84d4114cc5ea02b4772a6346701f" - integrity sha1-pd5GU42uhNQRTMXqArR3KmNGcB8= - dependencies: - source-map "^0.5.6" - merge-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" @@ -6886,21 +7599,11 @@ mime@^2.4.4: resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.4.tgz#bd7b91135fc6b01cde3e9bae33d659b63d8857e5" integrity sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA== -mimic-fn@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" - integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== - mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -mimic-response@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.0.0.tgz#996a51c60adf12cb8a87d7fb8ef24c2f3d5ebb46" - integrity sha512-8ilDoEapqA4uQ3TwS0jakGONKXVJqpy+RpM+3b7pLdOjghCrEiGp9SRkFbUHAmZW9vdnrENWHjaweIoTIJExSQ== - min-indent@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" @@ -6933,7 +7636,7 @@ minimist@^1.1.1, minimist@^1.2.5: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== -minimist@^1.1.3, minimist@^1.2.0: +minimist@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= @@ -6963,6 +7666,11 @@ ms@^2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== +mute-stream@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" + integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== + nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" @@ -6980,11 +7688,6 @@ nanomatch@^1.2.9: snapdragon "^0.8.1" to-regex "^3.0.1" -napi-build-utils@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.1.tgz#1381a0f92c39d66bf19852e7873432fc2123e508" - integrity sha512-boQj1WFgQH3v4clhu3mTNfP+vOBxorDlE8EKiMjUlLG3C4qAESnn9AxIOkFgTR2c9LtzNjPrjS60cT27ZKBhaA== - natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" @@ -7000,57 +7703,31 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== -node-abi@^2.7.0: - version "2.13.0" - resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.13.0.tgz#e2f2ec444d0aca3ea1b3874b6de41d1665828f63" - integrity sha512-9HrZGFVTR5SOu3PZAnAY2hLO36aW1wmA+FDsVkr85BTST32TLCA1H/AEcatVRAsWLyXS3bqUDYCAjq5/QGuSTA== - dependencies: - semver "^5.4.1" +node-addon-api@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" + integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== -node-addon-api@^1.6.2, node-addon-api@^1.7.1: - version "1.7.1" - resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-1.7.1.tgz#cf813cd69bb8d9100f6bdca6755fc268f54ac492" - integrity sha512-2+DuKodWvwRTrCfKOeR24KIc5unKjOh8mz17NCzVnHWfjAdDqbfbjqh7gUT+BkXBRQM52+xCHciKWonJ3CbJMQ== +node-addon-api@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.0.0.tgz#812446a1001a54f71663bed188314bba07e09247" + integrity sha512-sSHCgWfJ+Lui/u+0msF3oyCgvdkhxDbkCS6Q8uiJquzOimkJBvX6hl5aSSA7DR1XbMpdM8r7phjcF63sF4rkKg== node-forge@^0.8.1: version "0.8.5" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.8.5.tgz#57906f07614dc72762c84cef442f427c0e1b86ee" integrity sha512-vFMQIWt+J/7FLNyKouZ9TazT74PRV3wgv9UT4cRjC8BffxFbKXkgIWR42URCPSnHm/QDz6BOlb2Q0U4+VQT67Q== +node-gyp-build@^4.2.1, node-gyp-build@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.2.2.tgz#3f44b65adaafd42fb6c3d81afd630e45c847eb66" + integrity sha512-Lqh7mrByWCM8Cf9UPqpeoVBBo5Ugx+RKu885GAzmLBVYjeywScxHXPGLa4JfYNZmcNGwzR0Glu5/9GaQZMFqyA== + node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs= -node-libs-browser@^2.0.0, node-libs-browser@^2.1.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" - integrity sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q== - dependencies: - assert "^1.1.1" - browserify-zlib "^0.2.0" - buffer "^4.3.0" - console-browserify "^1.1.0" - constants-browserify "^1.0.0" - crypto-browserify "^3.11.0" - domain-browser "^1.1.1" - events "^3.0.0" - https-browserify "^1.0.0" - os-browserify "^0.3.0" - path-browserify "0.0.1" - process "^0.11.10" - punycode "^1.2.4" - querystring-es3 "^0.2.0" - readable-stream "^2.3.3" - stream-browserify "^2.0.1" - stream-http "^2.7.2" - string_decoder "^1.0.0" - timers-browserify "^2.0.4" - tty-browserify "0.0.0" - url "^0.11.0" - util "^0.11.0" - vm-browserify "^1.0.1" - node-modules-regexp@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz#8d9dbe28964a4ac5712e9131642107c71e90ec40" @@ -7080,19 +7757,6 @@ node-releases@^1.1.53: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.58.tgz#8ee20eef30fa60e52755fcc0942def5a734fe935" integrity sha512-NxBudgVKiRh/2aPWMgPR7bPTX0VPmGx5QBwCtdHitnqFE5/O8DeBXuIMH1nwNnw/aMo6AjOrpsHzfY3UbUJ7yg== -noop-logger@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/noop-logger/-/noop-logger-0.1.1.tgz#94a2b1633c4f1317553007d8966fd0e841b6a4c2" - integrity sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI= - -nopt@~4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" - integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00= - dependencies: - abbrev "1" - osenv "^0.1.4" - normalize-html-whitespace@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/normalize-html-whitespace/-/normalize-html-whitespace-1.0.0.tgz#5e3c8e192f1b06c3b9eee4b7e7f28854c7601e34" @@ -7139,16 +7803,6 @@ npm-run-path@^4.0.0: dependencies: path-key "^3.0.0" -npmlog@^4.0.1: - version "4.1.2" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" - integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== - dependencies: - are-we-there-yet "~1.1.2" - console-control-strings "~1.1.0" - gauge "~2.7.3" - set-blocking "~2.0.0" - nth-check@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" @@ -7161,11 +7815,6 @@ nullthrows@^1.1.1: resolved "https://registry.yarnpkg.com/nullthrows/-/nullthrows-1.1.1.tgz#7818258843856ae971eae4208ad7d7eb19a431b1" integrity sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw== -number-is-nan@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= - nwsapi@^2.1.3, nwsapi@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7" @@ -7176,7 +7825,7 @@ oauth-sign@~0.9.0: resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -object-assign@^4.1.0, object-assign@^4.1.1: +object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= @@ -7195,12 +7844,15 @@ object-inspect@^1.7.0: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67" integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw== -object-inspect@~1.4.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.4.1.tgz#37ffb10e71adaf3748d05f713b4c9452f402cbc4" - integrity sha512-wqdhLpfCUbEsoEwl3FXwGyv8ief1k/1aUdIPCqVnupM6e8l63BEJdiF/0swtn04/8p05tG/T0FrpTlfwvljOdw== +object-is@^1.0.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.2.tgz#c5d2e87ff9e119f78b7a088441519e2eec1573b6" + integrity sha512-5lHCz+0uufF6wZ7CRFWJN3hp8Jqblpgve06U5CMQ3f//6iDjPr2PEo9MWCjEssDsa+UZEL4PkFpr+BMop6aKzQ== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.5" -object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.0.6, object-keys@^1.1.1: +object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== @@ -7280,13 +7932,6 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0: dependencies: wrappy "1" -onetime@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" - integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ= - dependencies: - mimic-fn "^1.0.0" - onetime@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.0.tgz#fff0f3c91617fe62bb50189636e99ac8a6df7be5" @@ -7294,6 +7939,14 @@ onetime@^5.1.0: dependencies: mimic-fn "^2.1.0" +open@^7.0.3: + version "7.0.4" + resolved "https://registry.yarnpkg.com/open/-/open-7.0.4.tgz#c28a9d315e5c98340bf979fdcb2e58664aa10d83" + integrity sha512-brSA+/yq+b08Hsr4c8fsEW2CRzk1BmfN3SAK/5VCHQ9bdoZJ4qa/+AfR0xHjlbbZUyPkUHs1b8x1RqdyZdkVqQ== + dependencies: + is-docker "^2.0.0" + is-wsl "^2.1.1" + opn@5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/opn/-/opn-5.3.0.tgz#64871565c863875f052cfdf53d3e3cb5adb53b1c" @@ -7325,29 +7978,25 @@ optionator@^0.9.1: type-check "^0.4.0" word-wrap "^1.2.3" +ora@^4.0.3: + version "4.0.4" + resolved "https://registry.yarnpkg.com/ora/-/ora-4.0.4.tgz#e8da697cc5b6a47266655bf68e0fb588d29a545d" + integrity sha512-77iGeVU1cIdRhgFzCK8aw1fbtT1B/iZAvWjS+l/o1x0RShMgxHUZaD2yDpWsNCPwXg9z1ZA78Kbdvr8kBmG/Ww== + dependencies: + chalk "^3.0.0" + cli-cursor "^3.1.0" + cli-spinners "^2.2.0" + is-interactive "^1.0.0" + log-symbols "^3.0.0" + mute-stream "0.0.8" + strip-ansi "^6.0.0" + wcwidth "^1.0.1" + os-browserify@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= -os-homedir@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" - integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= - -os-tmpdir@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= - -osenv@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" - integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== - dependencies: - os-homedir "^1.0.0" - os-tmpdir "^1.0.0" - p-each-series@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-2.1.0.tgz#961c8dd3f195ea96c747e636b262b800a6b1af48" @@ -7400,6 +8049,13 @@ p-locate@^4.1.0: dependencies: p-limit "^2.2.0" +p-map@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" + integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== + dependencies: + aggregate-error "^3.0.0" + p-try@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" @@ -7410,26 +8066,23 @@ p-try@^2.0.0: resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== -pako@^0.2.5: - version "0.2.9" - resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75" - integrity sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU= - pako@~1.0.5: version "1.0.10" resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.10.tgz#4328badb5086a426aa90f541977d4955da5c9732" integrity sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw== -parcel@2.0.0-alpha.3.2: - version "2.0.0-alpha.3.2" - resolved "https://registry.yarnpkg.com/parcel/-/parcel-2.0.0-alpha.3.2.tgz#d59de34f491608197d4f9e40688545d62aada08e" - integrity sha512-FG8JZtY2MAhxYANtLUlRbPNhTqtDB6zDQ+GVPBgzs6xlzyWSEdzayJ2a25Nnee+SBptV9nSHavkMrtP3YLrnAg== - dependencies: - "@parcel/config-default" "^2.0.0-alpha.3.1" - "@parcel/core" "^2.0.0-alpha.3.2" - "@parcel/fs" "^2.0.0-alpha.3.1" - "@parcel/logger" "^2.0.0-alpha.3.1" - "@parcel/package-manager" "^2.0.0-alpha.3.1" +parcel@2.0.0-beta.1: + version "2.0.0-beta.1" + resolved "https://registry.yarnpkg.com/parcel/-/parcel-2.0.0-beta.1.tgz#7b23be0217da198f0e8f0d14f0107d8d938074dd" + integrity sha512-Z2tzZoDws7q+99ihjpd3WX09BTao2miTk+S9URJXRJkVxxgoZSQJ+uwtxcosoDWwS6zv4RAXxtEMmiyMeaCuMQ== + dependencies: + "@parcel/config-default" "2.0.0-beta.1" + "@parcel/core" "2.0.0-beta.1" + "@parcel/diagnostic" "2.0.0-beta.1" + "@parcel/fs" "2.0.0-beta.1" + "@parcel/logger" "2.0.0-beta.1" + "@parcel/package-manager" "2.0.0-beta.1" + "@parcel/utils" "2.0.0-beta.1" chalk "^2.1.0" commander "^2.19.0" get-port "^4.2.0" @@ -7498,10 +8151,10 @@ pascalcase@^0.1.1: resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= -path-browserify@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" - integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ== +path-browserify@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" + integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== path-exists@^3.0.0: version "3.0.0" @@ -7554,11 +8207,6 @@ performance-now@^2.1.0: resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= -physical-cpu-count@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/physical-cpu-count/-/physical-cpu-count-2.0.0.tgz#18de2f97e4bf7a9551ad7511942b5496f7aba660" - integrity sha1-GN4vl+S/epVRrXURlCtUlverpmA= - picomatch@^2.0.4: version "2.2.2" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" @@ -7569,7 +8217,7 @@ picomatch@^2.0.5: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.1.tgz#21bac888b6ed8601f831ce7816e335bc779f0a4a" integrity sha512-ISBaA8xQNmwELC7eOjqFKMESB2VIqt4PPDD0nsS95b/9dZXvVKOlz9keMSnoGGKcOHXfTvDD6WMaRoSc9UuhRA== -pirates@^4.0.0, pirates@^4.0.1: +pirates@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.1.tgz#643a92caf894566f91b2b986d2c66950a8e2fb87" integrity sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA== @@ -7590,6 +8238,13 @@ pkg-up@^2.0.0: dependencies: find-up "^2.1.0" +please-upgrade-node@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz#aeddd3f994c933e4ad98b99d9a556efa0e2fe942" + integrity sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg== + dependencies: + semver-compare "^1.0.0" + pn@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb" @@ -7977,27 +8632,6 @@ posthtml@^0.12.0: posthtml-parser "^0.4.1" posthtml-render "^1.1.5" -prebuild-install@^5.2.5: - version "5.3.3" - resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-5.3.3.tgz#ef4052baac60d465f5ba6bf003c9c1de79b9da8e" - integrity sha512-GV+nsUXuPW2p8Zy7SarF/2W/oiK8bFQgJcncoJ0d7kRpekEA0ftChjfEaF9/Y+QJEc/wFR7RAEa8lYByuUIe2g== - dependencies: - detect-libc "^1.0.3" - expand-template "^2.0.3" - github-from-package "0.0.0" - minimist "^1.2.0" - mkdirp "^0.5.1" - napi-build-utils "^1.0.1" - node-abi "^2.7.0" - noop-logger "^0.1.1" - npmlog "^4.0.1" - pump "^3.0.0" - rc "^1.2.7" - simple-get "^3.0.3" - tar-fs "^2.0.0" - tunnel-agent "^0.6.0" - which-pm-runs "^1.0.0" - prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" @@ -8068,7 +8702,7 @@ prompts@^2.0.1: kleur "^3.0.3" sisteransi "^1.0.4" -prop-types@^15.5.10, prop-types@^15.6.2, prop-types@^15.7.2: +prop-types@^15.6.2, prop-types@^15.7.2: version "15.7.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== @@ -8077,16 +8711,6 @@ prop-types@^15.5.10, prop-types@^15.6.2, prop-types@^15.7.2: object-assign "^4.1.1" react-is "^16.8.1" -proto-list@~1.2.1: - version "1.2.4" - resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" - integrity sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk= - -pseudomap@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" - integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= - psl@^1.1.24, psl@^1.1.28: version "1.7.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.7.0.tgz#f1c4c47a8ef97167dea5d6bbf4816d736e884a3c" @@ -8117,7 +8741,7 @@ punycode@1.3.2: resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= -punycode@^1.2.4, punycode@^1.4.1: +punycode@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= @@ -8147,7 +8771,7 @@ qs@~6.5.2: resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== -querystring-es3@^0.2.0: +querystring-es3@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM= @@ -8157,15 +8781,6 @@ querystring@0.2.0: resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= -quote-stream@^1.0.1, quote-stream@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/quote-stream/-/quote-stream-1.0.2.tgz#84963f8c9c26b942e153feeb53aae74652b7e0b2" - integrity sha1-hJY/jJwmuULhU/7rU6rnRlK34LI= - dependencies: - buffer-equal "0.0.1" - minimist "^1.1.3" - through2 "^2.0.0" - randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" @@ -8181,16 +8796,6 @@ randomfill@^1.0.3: randombytes "^2.0.5" safe-buffer "^5.1.0" -rc@^1.2.7: - version "1.2.8" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== - dependencies: - deep-extend "^0.6.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" - react-dom@^16.13.1: version "16.13.1" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.13.1.tgz#c1bd37331a0486c078ee54c4740720993b2e0e7f" @@ -8211,16 +8816,6 @@ react-is@^16.8.1: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.12.0.tgz#2cc0fe0fba742d97fd527c42a13bec4eeb06241c" integrity sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q== -react-reconciler@^0.24.0: - version "0.24.0" - resolved "https://registry.yarnpkg.com/react-reconciler/-/react-reconciler-0.24.0.tgz#5a396b2c2f5efe8554134a5935f49f546723f2dd" - integrity sha512-gAGnwWkf+NOTig9oOowqid9O0HjTDC+XVGBCAmJYYJ2A2cN/O4gDdIuuUQjv8A4v6GDwVfJkagpBBLW5OW9HSw== - dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" - prop-types "^15.6.2" - scheduler "^0.18.0" - react-refresh@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.6.0.tgz#81971b8f3c8c05aaa6ce87491ae41b396133f896" @@ -8268,7 +8863,7 @@ read-pkg@^5.2.0: parse-json "^5.0.0" type-fest "^0.6.0" -readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.3, readable-stream@~2.3.6: +"readable-stream@1 || 2": version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== @@ -8281,7 +8876,7 @@ readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.2.2, readable string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.0.0, readable-stream@^3.0.1, readable-stream@^3.1.1: +readable-stream@^3.0.0, readable-stream@^3.1.1: version "3.4.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.4.0.tgz#a51c26754658e0a3c21dbf59163bd45ba6f447fc" integrity sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ== @@ -8290,6 +8885,15 @@ readable-stream@^3.0.0, readable-stream@^3.0.1, readable-stream@^3.1.1: string_decoder "^1.1.1" util-deprecate "^1.0.1" +readable-stream@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" + integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + redent@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f" @@ -8317,11 +8921,6 @@ regenerate@^1.2.1, regenerate@^1.4.0: resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg== -regenerator-runtime@^0.11.0: - version "0.11.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" - integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== - regenerator-runtime@^0.13.4: version "0.13.5" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz#d878a1d094b4306d10b9096484b33ebd55e26697" @@ -8557,13 +9156,6 @@ resolve-url@^0.2.1: resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= -resolve@^1.1.5, resolve@^1.12.0, resolve@^1.3.2: - version "1.14.2" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.14.2.tgz#dbf31d0fa98b1f29aa5169783b9c290cb865fea2" - integrity sha512-EjlOBLBO1kxsUxsKjLt7TAECyKW6fOh1VRkykQkKGzcBbjjPIxBqGh0jf7GJ3k/f5mxMqW3htMD3WdTUVtW8HQ== - dependencies: - path-parse "^1.0.6" - resolve@^1.10.0, resolve@^1.15.1, resolve@^1.17.0, resolve@^1.8.1: version "1.17.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" @@ -8571,13 +9163,12 @@ resolve@^1.10.0, resolve@^1.15.1, resolve@^1.17.0, resolve@^1.8.1: dependencies: path-parse "^1.0.6" -restore-cursor@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" - integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368= +resolve@^1.12.0, resolve@^1.3.2: + version "1.14.2" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.14.2.tgz#dbf31d0fa98b1f29aa5169783b9c290cb865fea2" + integrity sha512-EjlOBLBO1kxsUxsKjLt7TAECyKW6fOh1VRkykQkKGzcBbjjPIxBqGh0jf7GJ3k/f5mxMqW3htMD3WdTUVtW8HQ== dependencies: - onetime "^2.0.0" - signal-exit "^3.0.2" + path-parse "^1.0.6" restore-cursor@^3.1.0: version "3.1.0" @@ -8646,6 +9237,13 @@ run-parallel@^1.1.9: resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" integrity sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q== +rxjs@^6.5.5: + version "6.6.0" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.0.tgz#af2901eedf02e3a83ffa7f886240ff9018bbec84" + integrity sha512-3HMA8z/Oz61DUHe+SdOiQyzIf4tOx5oQHmMir7IZEu6TMqCLHT4LRcmNaUS0NwOz8VLvmmBduMsoaUvMaIiqzg== + dependencies: + tslib "^1.9.0" + safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" @@ -8668,13 +9266,6 @@ safe-regex@^1.1.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -safer-eval@^1.3.0: - version "1.3.6" - resolved "https://registry.yarnpkg.com/safer-eval/-/safer-eval-1.3.6.tgz#ee51e3348c39fdc4117a47dfb4b69df56a2e40cf" - integrity sha512-DN9tBsZgtUOHODzSfO1nGCLhZtxc7Qq/d8/2SNxQZ9muYXZspSh1fO7HOsrf4lcelBNviAJLCxB/ggmG+jV1aw== - dependencies: - clones "^1.2.0" - sane@^4.0.3: version "4.1.0" resolved "https://registry.yarnpkg.com/sane/-/sane-4.1.0.tgz#ed881fd922733a6c461bc189dc2b6c006f3ffded" @@ -8709,14 +9300,6 @@ saxes@^5.0.0: dependencies: xmlchars "^2.2.0" -scheduler@^0.18.0: - version "0.18.0" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.18.0.tgz#5901ad6659bc1d8f3fdaf36eb7a67b0d6746b1c4" - integrity sha512-agTSHR1Nbfi6ulI0kYNK0203joW2Y5W4po4l+v03tOoiJKpTBbxpNhWDvqc/4IcOw+KLmSiQLTasZ4cab2/UWQ== - dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" - scheduler@^0.19.1: version "0.19.1" resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.19.1.tgz#4f3e2ed2c1a7d65681f4c854fa8c5a1ccb40f196" @@ -8725,7 +9308,12 @@ scheduler@^0.19.1: loose-envify "^1.1.0" object-assign "^4.1.1" -"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0: +semver-compare@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" + integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w= + +"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.7.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== @@ -8745,15 +9333,12 @@ semver@^7.2.1, semver@^7.3.2: resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== -serialize-to-js@^1.1.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/serialize-to-js/-/serialize-to-js-1.2.2.tgz#1a567b0c9bf557bc7d7b77b503dfae0a8218d15d" - integrity sha512-mUc8vA5iJghe+O+3s0YDGFLMJcqitVFk787YKiv8a4sf6RX5W0u81b+gcHrp15O0fFa010dRBVZvwcKXOWsL9Q== - dependencies: - js-beautify "^1.8.9" - safer-eval "^1.3.0" +serialize-to-js@^3.0.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/serialize-to-js/-/serialize-to-js-3.1.1.tgz#b3e77d0568ee4a60bfe66287f991e104d3a1a4ac" + integrity sha512-F+NGU0UHMBO4Q965tjw7rvieNVjlH6Lqi2emq/Lc9LUURYJbiCzmpi4Cy1OOjjVPtxu0c+NE85LU6968Wko5ZA== -set-blocking@^2.0.0, set-blocking@~2.0.0: +set-blocking@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= @@ -8781,11 +9366,6 @@ sha.js@^2.4.0, sha.js@^2.4.8: inherits "^2.0.1" safe-buffer "^5.0.1" -shallow-copy@~0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/shallow-copy/-/shallow-copy-0.0.1.tgz#415f42702d73d810330292cc5ee86eae1a11a170" - integrity sha1-QV9CcC1z2BAzApLMXuhurhoRoXA= - shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" @@ -8823,30 +9403,11 @@ side-channel@^1.0.2: es-abstract "^1.17.0-next.1" object-inspect "^1.7.0" -sigmund@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" - integrity sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA= - signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= -simple-concat@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.0.tgz#7344cbb8b6e26fb27d66b2fc86f9f6d5997521c6" - integrity sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY= - -simple-get@^3.0.3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-3.1.0.tgz#b45be062435e50d159540b576202ceec40b9c6b3" - integrity sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA== - dependencies: - decompress-response "^4.2.0" - once "^1.3.1" - simple-concat "^1.0.0" - simple-swizzle@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" @@ -8882,6 +9443,15 @@ slice-ansi@^3.0.0: astral-regex "^2.0.0" is-fullwidth-code-point "^3.0.0" +slice-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" + integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + snapdragon-node@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" @@ -9031,13 +9601,6 @@ stack-utils@^2.0.2: dependencies: escape-string-regexp "^2.0.0" -static-eval@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/static-eval/-/static-eval-2.0.3.tgz#cb62fc79946bd4d5f623a45ad428233adace4d72" - integrity sha512-zsxDGucfAh8T339sSKgpFbvg15Fms2IVaJGC+jqp0bVsxhcpM+iMeAI8weNo8dmf4OblgifTBUoyk1vGVtYw2w== - dependencies: - escodegen "^1.11.1" - static-extend@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" @@ -9046,26 +9609,6 @@ static-extend@^0.1.1: define-property "^0.2.5" object-copy "^0.1.0" -static-module@^2.2.0: - version "2.2.5" - resolved "https://registry.yarnpkg.com/static-module/-/static-module-2.2.5.tgz#bd40abceae33da6b7afb84a0e4329ff8852bfbbf" - integrity sha512-D8vv82E/Kpmz3TXHKG8PPsCPg+RAX6cbCOyvjM6x04qZtQ47EtJFVwRsdov3n5d6/6ynrOY9XB4JkaZwB2xoRQ== - dependencies: - concat-stream "~1.6.0" - convert-source-map "^1.5.1" - duplexer2 "~0.1.4" - escodegen "~1.9.0" - falafel "^2.1.0" - has "^1.0.1" - magic-string "^0.22.4" - merge-source-map "1.0.4" - object-inspect "~1.4.0" - quote-stream "~1.0.2" - readable-stream "~2.3.3" - shallow-copy "~0.0.1" - static-eval "^2.0.0" - through2 "~2.0.3" - statuses@~1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" @@ -9076,38 +9619,26 @@ stealthy-require@^1.1.1: resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= -stream-browserify@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" - integrity sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg== - dependencies: - inherits "~2.0.1" - readable-stream "^2.0.2" - -stream-http@^2.7.2: - version "2.8.3" - resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" - integrity sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw== +stream-http@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-3.1.1.tgz#0370a8017cf8d050b9a8554afe608f043eaff564" + integrity sha512-S7OqaYu0EkFpgeGFb/NPOoPLxFko7TPqtEeFg5DXPB4v/KETHG0Ln6fRFrNezoelpaDKmycEmmZ81cC9DAwgYg== dependencies: builtin-status-codes "^3.0.0" - inherits "^2.0.1" - readable-stream "^2.3.6" - to-arraybuffer "^1.0.0" - xtend "^4.0.0" + inherits "^2.0.4" + readable-stream "^3.6.0" + xtend "^4.0.2" + +string-argv@0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.1.tgz#95e2fbec0427ae19184935f816d74aaa4c5c19da" + integrity sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg== string-hash@^1.1.1: version "1.1.3" resolved "https://registry.yarnpkg.com/string-hash/-/string-hash-1.1.3.tgz#e8aafc0ac1855b4666929ed7dd1275df5d6c811b" integrity sha1-6Kr8CsGFW0Zmkp7X3RJ1311sgRs= -string-length@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/string-length/-/string-length-3.1.0.tgz#107ef8c23456e187a8abd4a61162ff4ac6e25837" - integrity sha512-Ttp5YvkGm5v9Ijagtaz1BnN+k9ObpvS0eIBblPMp2YWL8FBmi9qblQ9fexc2k/CXFgrTIteU3jAw3payCnwSTA== - dependencies: - astral-regex "^1.0.0" - strip-ansi "^5.2.0" - string-length@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.1.tgz#4a973bf31ef77c4edbceadd6af2611996985f8a1" @@ -9121,23 +9652,6 @@ string-natural-compare@^3.0.1: resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-3.0.1.tgz#7a42d58474454963759e8e8b7ae63d71c1e7fdf4" integrity sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw== -string-width@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - strip-ansi "^3.0.0" - -"string-width@^1.0.2 || 2": - version "2.1.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.0" - string-width@^3.0.0, string-width@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" @@ -9147,7 +9661,7 @@ string-width@^3.0.0, string-width@^3.1.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" -string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0: +string-width@^4.1.0, string-width@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== @@ -9200,7 +9714,7 @@ string.prototype.trimstart@^1.0.1: define-properties "^1.1.3" es-abstract "^1.17.5" -string_decoder@^1.0.0, string_decoder@^1.1.1: +string_decoder@^1.1.1, string_decoder@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== @@ -9214,20 +9728,22 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -strip-ansi@^3.0.0, strip-ansi@^3.0.1: +stringify-object@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/stringify-object/-/stringify-object-3.3.0.tgz#703065aefca19300d3ce88af4f5b3956d7556629" + integrity sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw== + dependencies: + get-own-enumerable-property-symbols "^3.0.0" + is-obj "^1.0.1" + is-regexp "^1.0.0" + +strip-ansi@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= dependencies: ansi-regex "^2.0.0" -strip-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= - dependencies: - ansi-regex "^3.0.0" - strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" @@ -9269,11 +9785,6 @@ strip-json-comments@^3.1.0: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.0.tgz#7638d31422129ecf4457440009fba03f9f9ac180" integrity sha512-e6/d0eBu7gHtdCqFt0xJr642LdToM5/cN4Qb9DbHjVx1CP5RyeM+zH7pbecEmDv/lBqb0QH+6Uqq75rxFPkM0w== -strip-json-comments@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= - stylehacks@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-4.0.3.tgz#6718fcaf4d1e07d8a1318690881e8d96726a71d5" @@ -9358,26 +9869,10 @@ table@^5.2.3: slice-ansi "^2.1.0" string-width "^3.0.0" -tar-fs@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.0.0.tgz#677700fc0c8b337a78bee3623fdc235f21d7afad" - integrity sha512-vaY0obB6Om/fso8a8vakQBzwholQ7v5+uy+tF3Ozvxv1KNezmVQAiWtcNmMHFSFPqL3dJA8ha6gdtFbfX9mcxA== - dependencies: - chownr "^1.1.1" - mkdirp "^0.5.1" - pump "^3.0.0" - tar-stream "^2.0.0" - -tar-stream@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.1.0.tgz#d1aaa3661f05b38b5acc9b7020efdca5179a2cc3" - integrity sha512-+DAn4Nb4+gz6WZigRzKEZl1QuJVOLtAwwF+WUxy1fJ6X63CaGaUAxJRD2KEn1OMfcbCjySTYpNC6WmfQoIEOdw== - dependencies: - bl "^3.0.0" - end-of-stream "^1.4.1" - fs-constants "^1.0.0" - inherits "^2.0.3" - readable-stream "^3.1.1" +term-size@^2.1.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/term-size/-/term-size-2.2.0.tgz#1f16adedfe9bdc18800e1776821734086fcc6753" + integrity sha512-a6sumDlzyHVJWb8+YofY4TW112G6p2FCPEAFk+59gIYHv3XHRhm9ltVQ9kli4hNWeQBwSpe8cRN25x0ROunMOw== terminal-link@^2.0.0: version "2.1.1" @@ -9396,7 +9891,16 @@ terser@^3.7.3: source-map "~0.6.1" source-map-support "~0.5.10" -terser@^4.0.0, terser@^4.3.9: +terser@^4.3.0: + version "4.8.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.8.0.tgz#63056343d7c70bb29f3af665865a46fe03a0df17" + integrity sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw== + dependencies: + commander "^2.20.0" + source-map "~0.6.1" + source-map-support "~0.5.12" + +terser@^4.3.9: version "4.6.1" resolved "https://registry.yarnpkg.com/terser/-/terser-4.6.1.tgz#913e35e0d38a75285a7913ba01d753c4089ebdbd" integrity sha512-w0f2OWFD7ka3zwetgVAhNMeyzEbj39ht2Tb0qKflw9PmW9Qbo5tjTh01QJLkhO9t9RDDQYvk+WXqpECI2C6i2A== @@ -9424,15 +9928,12 @@ throat@^5.0.0: resolved "https://registry.yarnpkg.com/throat/-/throat-5.0.0.tgz#c5199235803aad18754a667d659b5e72ce16764b" integrity sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA== -through2@^2.0.0, through2@~2.0.3: - version "2.0.5" - resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" - integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== - dependencies: - readable-stream "~2.3.6" - xtend "~4.0.1" +through@^2.3.8: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= -timers-browserify@^2.0.4: +timers-browserify@^2.0.11: version "2.0.11" resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.11.tgz#800b1f3eee272e5bc53ee465a04d0e804c31211f" integrity sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ== @@ -9444,26 +9945,11 @@ timsort@^0.3.0: resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= -tiny-inflate@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/tiny-inflate/-/tiny-inflate-1.0.3.tgz#122715494913a1805166aaf7c93467933eea26c4" - integrity sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw== - tmpl@1.0.x: version "1.0.4" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" integrity sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE= -to-arraybuffer@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" - integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= - -to-fast-properties@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" - integrity sha1-uDVx+k2MJbguIxsG46MFXeTKGkc= - to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" @@ -9557,10 +10043,10 @@ tsutils@^3.17.1: dependencies: tslib "^1.8.1" -tty-browserify@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" - integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY= +tty-browserify@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.1.tgz#3f05251ee17904dfd0677546670db9651682b811" + integrity sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw== tunnel-agent@^0.6.0: version "0.6.0" @@ -9593,6 +10079,11 @@ type-detect@4.0.8: resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== +type-fest@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.11.0.tgz#97abf0872310fed88a5c466b25681576145e33f1" + integrity sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ== + type-fest@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" @@ -9610,11 +10101,6 @@ typedarray-to-buffer@^3.1.5: dependencies: is-typedarray "^1.0.0" -typedarray@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" - integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= - uncss@^0.17.2: version "0.17.2" resolved "https://registry.yarnpkg.com/uncss/-/uncss-0.17.2.tgz#fac1c2429be72108e8a47437c647d58cf9ea66f1" @@ -9658,14 +10144,6 @@ unicode-property-aliases-ecmascript@^1.0.4: resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz#a9cc6cc7ce63a0a3023fc99e341b94431d405a57" integrity sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw== -unicode-trie@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/unicode-trie/-/unicode-trie-0.3.1.tgz#d671dddd89101a08bac37b6a5161010602052085" - integrity sha1-1nHd3YkQGgi6w3tqUWEBBgIFIIU= - dependencies: - pako "^0.2.5" - tiny-inflate "^1.0.0" - union-value@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" @@ -9742,19 +10220,17 @@ util.promisify@~1.0.0: define-properties "^1.1.2" object.getownpropertydescriptors "^2.0.3" -util@0.10.3: - version "0.10.3" - resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" - integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk= - dependencies: - inherits "2.0.1" - -util@^0.11.0: - version "0.11.1" - resolved "https://registry.yarnpkg.com/util/-/util-0.11.1.tgz#3236733720ec64bb27f6e26f421aaa2e1b588d61" - integrity sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ== +util@^0.12.0, util@^0.12.3: + version "0.12.3" + resolved "https://registry.yarnpkg.com/util/-/util-0.12.3.tgz#971bb0292d2cc0c892dab7c6a5d37c2bec707888" + integrity sha512-I8XkoQwE+fPQEhy9v012V+TSdH2kp9ts29i20TaaDUXsg7x/onePbhFJUExBfv/2ay1ZOp/Vsm3nDlmnFGSAog== dependencies: - inherits "2.0.3" + inherits "^2.0.3" + is-arguments "^1.0.4" + is-generator-function "^1.0.7" + is-typed-array "^1.1.3" + safe-buffer "^5.1.2" + which-typed-array "^1.1.2" utils-merge@1.0.1: version "1.0.1" @@ -9812,12 +10288,7 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" -vlq@^0.2.2: - version "0.2.3" - resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.3.tgz#8f3e4328cf63b1540c0d67e1b2778386f8975b26" - integrity sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow== - -vm-browserify@^1.0.1: +vm-browserify@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== @@ -9859,6 +10330,13 @@ walker@^1.0.7, walker@~1.0.5: dependencies: makeerror "1.0.x" +wcwidth@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" + integrity sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g= + dependencies: + defaults "^1.0.3" + webidl-conversions@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" @@ -9909,10 +10387,17 @@ which-module@^2.0.0: resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= -which-pm-runs@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/which-pm-runs/-/which-pm-runs-1.0.0.tgz#670b3afbc552e0b55df6b7780ca74615f23ad1cb" - integrity sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs= +which-typed-array@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.2.tgz#e5f98e56bda93e3dac196b01d47c1156679c00b2" + integrity sha512-KT6okrd1tE6JdZAy3o2VhMoYPh3+J6EMZLyrxBQsZflI1QCZIxMrIYLkosd8Twf+YfknVIHmYQPgJt238p8dnQ== + dependencies: + available-typed-arrays "^1.0.2" + es-abstract "^1.17.5" + foreach "^2.0.5" + function-bind "^1.1.1" + has-symbols "^1.0.1" + is-typed-array "^1.1.3" which@^1.2.9: version "1.3.1" @@ -9928,26 +10413,12 @@ which@^2.0.1, which@^2.0.2: dependencies: isexe "^2.0.0" -wide-align@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" - integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== - dependencies: - string-width "^1.0.2 || 2" - -widest-line@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca" - integrity sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg== - dependencies: - string-width "^4.0.0" - word-wrap@^1.2.3, word-wrap@~1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== -wrap-ansi@^5.0.0, wrap-ansi@^5.1.0: +wrap-ansi@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== @@ -10016,7 +10487,7 @@ xregexp@^4.3.0: dependencies: "@babel/runtime-corejs3" "^7.8.3" -xtend@^4.0.0, xtend@~4.0.1: +xtend@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== @@ -10026,11 +10497,6 @@ y18n@^4.0.0: resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== -yallist@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" - integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= - yaml@^1.7.2: version "1.10.0" resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.0.tgz#3b593add944876077d4d683fee01081bd9fff31e" @@ -10085,8 +10551,3 @@ yargs@^15.3.1: which-module "^2.0.0" y18n "^4.0.0" yargs-parser "^18.1.1" - -yoga-layout-prebuilt@^1.9.3: - version "1.9.3" - resolved "https://registry.yarnpkg.com/yoga-layout-prebuilt/-/yoga-layout-prebuilt-1.9.3.tgz#11e3be29096afe3c284e5d963cc2d628148c1372" - integrity sha512-9SNQpwuEh2NucU83i2KMZnONVudZ86YNcFk9tq74YaqrQfgJWO3yB9uzH1tAg8iqh5c9F5j0wuyJ2z72wcum2w== From 3a5e6635baac93edf8e8c15154f65cfb5db514cb Mon Sep 17 00:00:00 2001 From: Kartik Choudhary Date: Wed, 8 Jul 2020 21:50:15 +0530 Subject: [PATCH 039/116] Decrease lane height by 1/3, add note to react_gutter_size --- src/canvas/constants.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/canvas/constants.js b/src/canvas/constants.js index 403b2d054e6e3..f8603834568b7 100644 --- a/src/canvas/constants.js +++ b/src/canvas/constants.js @@ -44,12 +44,12 @@ export const TEXT_CSS_PIXELS_OFFSET_TOP = 11; export const FONT_SIZE = 10; export const BORDER_OPACITY = 0.4; -export const REACT_GUTTER_SIZE = 0; +export const REACT_GUTTER_SIZE = 0; //Increase to add vertical padding to lanes export const REACT_EVENT_ROW_PADDING = 4; export const REACT_EVENT_SIZE = 6; -export const REACT_WORK_SIZE = 12; +export const REACT_WORK_SIZE = 9; export const REACT_EVENT_BORDER_SIZE = 1; -export const REACT_PRIORITY_BORDER_SIZE = 1; +export const REACT_PRIORITY_BORDER_SIZE = 0.7; export const FLAMECHART_FONT_SIZE = 10; export const FLAMECHART_FRAME_HEIGHT = 16; From 0a67c9653dff99ccc4a43b2a2912c62be23ddb69 Mon Sep 17 00:00:00 2001 From: Kartik Choudhary Date: Wed, 8 Jul 2020 23:57:41 +0530 Subject: [PATCH 040/116] Revert lane border size, rename REACT_PRIORITY_BORDER_SIZE to REACT_WORK_BORDER_SIZE --- src/canvas/canvasUtils.js | 4 ++-- src/canvas/constants.js | 6 +++--- src/canvas/renderCanvas.js | 18 +++++++++--------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/canvas/canvasUtils.js b/src/canvas/canvasUtils.js index 1bec3f3327278..ae76961bc4aaf 100644 --- a/src/canvas/canvasUtils.js +++ b/src/canvas/canvasUtils.js @@ -9,7 +9,7 @@ import { MAX_INTERVAL_SIZE_PX, REACT_GUTTER_SIZE, REACT_WORK_SIZE, - REACT_PRIORITY_BORDER_SIZE, + REACT_WORK_BORDER_SIZE, } from './constants'; // hidpi canvas: https://www.html5rocks.com/en/tutorials/canvas/hidpi/ @@ -101,6 +101,6 @@ export const getLaneHeight = ( REACT_GUTTER_SIZE + REACT_WORK_SIZE + REACT_GUTTER_SIZE + - REACT_PRIORITY_BORDER_SIZE + REACT_WORK_BORDER_SIZE ); }; diff --git a/src/canvas/constants.js b/src/canvas/constants.js index f8603834568b7..211936ea063c1 100644 --- a/src/canvas/constants.js +++ b/src/canvas/constants.js @@ -49,14 +49,14 @@ export const REACT_EVENT_ROW_PADDING = 4; export const REACT_EVENT_SIZE = 6; export const REACT_WORK_SIZE = 9; export const REACT_EVENT_BORDER_SIZE = 1; -export const REACT_PRIORITY_BORDER_SIZE = 0.7; +export const REACT_WORK_BORDER_SIZE = 1; export const FLAMECHART_FONT_SIZE = 10; export const FLAMECHART_FRAME_HEIGHT = 16; export const FLAMECHART_TEXT_PADDING = 3; -export const LABEL_FIXED_WIDTH = LABEL_SIZE + REACT_PRIORITY_BORDER_SIZE; -export const HEADER_HEIGHT_FIXED = MARKER_HEIGHT + REACT_PRIORITY_BORDER_SIZE; +export const LABEL_FIXED_WIDTH = LABEL_SIZE + REACT_WORK_BORDER_SIZE; +export const HEADER_HEIGHT_FIXED = MARKER_HEIGHT + REACT_WORK_BORDER_SIZE; export const EVENT_ROW_HEIGHT_FIXED = REACT_EVENT_ROW_PADDING + REACT_EVENT_SIZE + REACT_EVENT_ROW_PADDING; diff --git a/src/canvas/renderCanvas.js b/src/canvas/renderCanvas.js index 13d2291d16f57..a273de181feeb 100644 --- a/src/canvas/renderCanvas.js +++ b/src/canvas/renderCanvas.js @@ -31,7 +31,7 @@ import { MARKER_TICK_HEIGHT, REACT_GUTTER_SIZE, REACT_WORK_SIZE, - REACT_PRIORITY_BORDER_SIZE, + REACT_WORK_BORDER_SIZE, FLAMECHART_FONT_SIZE, FLAMECHART_FRAME_HEIGHT, FLAMECHART_TEXT_PADDING, @@ -146,10 +146,10 @@ function renderReactEventRow( canvasStartY + EVENT_ROW_HEIGHT_FIXED - offsetY - - REACT_PRIORITY_BORDER_SIZE, + REACT_WORK_BORDER_SIZE, ), canvasWidth, - REACT_PRIORITY_BORDER_SIZE, + REACT_WORK_BORDER_SIZE, ); return canvasStartY + EVENT_ROW_HEIGHT_FIXED; @@ -287,9 +287,9 @@ function renderReactMeasures( context.fillStyle = COLORS.PRIORITY_BORDER; context.fillRect( 0, - Math.floor(laneMinY - offsetY - REACT_PRIORITY_BORDER_SIZE), + Math.floor(laneMinY - offsetY - REACT_WORK_BORDER_SIZE), canvasWidth, - REACT_PRIORITY_BORDER_SIZE, + REACT_WORK_BORDER_SIZE, ); }); @@ -427,8 +427,8 @@ function renderFlamechart( context.fillRect( x, layerY, - Math.floor(width - REACT_PRIORITY_BORDER_SIZE), - Math.floor(FLAMECHART_FRAME_HEIGHT - REACT_PRIORITY_BORDER_SIZE), + Math.floor(width - REACT_WORK_BORDER_SIZE), + Math.floor(FLAMECHART_FRAME_HEIGHT - REACT_WORK_BORDER_SIZE), ); if (width > FLAMECHART_TEXT_PADDING * 2) { @@ -461,7 +461,7 @@ function renderAxisMarkers( context.fillRect(0, 0, canvasWidth, HEADER_HEIGHT_FIXED); context.fillStyle = COLORS.PRIORITY_BORDER; - context.fillRect(0, MARKER_HEIGHT, canvasWidth, REACT_PRIORITY_BORDER_SIZE); + context.fillRect(0, MARKER_HEIGHT, canvasWidth, REACT_WORK_BORDER_SIZE); // Charting data renders within this region of pixels as "scrollable" content. // Time markers (top) and priority labels (left) are fixed content. @@ -487,7 +487,7 @@ function renderAxisMarkers( context.fillRect( x, MARKER_HEIGHT - MARKER_TICK_HEIGHT, - REACT_PRIORITY_BORDER_SIZE, + REACT_WORK_BORDER_SIZE, MARKER_TICK_HEIGHT, ); From 8ce533f264fe3cf7c5a099129f9e1584df38e8fb Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Thu, 9 Jul 2020 09:59:10 +0800 Subject: [PATCH 041/116] Run Prettier --- src/canvas/constants.js | 2 +- src/canvas/renderCanvas.js | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/canvas/constants.js b/src/canvas/constants.js index 211936ea063c1..f90ede535ac82 100644 --- a/src/canvas/constants.js +++ b/src/canvas/constants.js @@ -44,7 +44,7 @@ export const TEXT_CSS_PIXELS_OFFSET_TOP = 11; export const FONT_SIZE = 10; export const BORDER_OPACITY = 0.4; -export const REACT_GUTTER_SIZE = 0; //Increase to add vertical padding to lanes +export const REACT_GUTTER_SIZE = 0; //Increase to add vertical padding to lanes export const REACT_EVENT_ROW_PADDING = 4; export const REACT_EVENT_SIZE = 6; export const REACT_WORK_SIZE = 9; diff --git a/src/canvas/renderCanvas.js b/src/canvas/renderCanvas.js index a273de181feeb..3737c1c4ddd6c 100644 --- a/src/canvas/renderCanvas.js +++ b/src/canvas/renderCanvas.js @@ -143,10 +143,7 @@ function renderReactEventRow( context.fillRect( 0, Math.floor( - canvasStartY + - EVENT_ROW_HEIGHT_FIXED - - offsetY - - REACT_WORK_BORDER_SIZE, + canvasStartY + EVENT_ROW_HEIGHT_FIXED - offsetY - REACT_WORK_BORDER_SIZE, ), canvasWidth, REACT_WORK_BORDER_SIZE, From b6407434742356f7b652673f6aa86aa008613d5c Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Thu, 9 Jul 2020 10:14:36 +0800 Subject: [PATCH 042/116] Fix nit: add space before comment text --- src/canvas/constants.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/canvas/constants.js b/src/canvas/constants.js index f90ede535ac82..09b58a59f335e 100644 --- a/src/canvas/constants.js +++ b/src/canvas/constants.js @@ -44,7 +44,7 @@ export const TEXT_CSS_PIXELS_OFFSET_TOP = 11; export const FONT_SIZE = 10; export const BORDER_OPACITY = 0.4; -export const REACT_GUTTER_SIZE = 0; //Increase to add vertical padding to lanes +export const REACT_GUTTER_SIZE = 0; // Increase to add vertical padding to lanes export const REACT_EVENT_ROW_PADDING = 4; export const REACT_EVENT_SIZE = 6; export const REACT_WORK_SIZE = 9; From bdf7e65c25214bac3c1f926a1438b1d45de9fca1 Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Thu, 9 Jul 2020 12:08:07 +0800 Subject: [PATCH 043/116] Add Prettier errors to ESLint (#61) * Add Prettier errors to ESLint * Upgrade dependencies --- .eslintrc.js | 4 +- package.json | 21 +- yarn.lock | 795 +++++++++++++++++++++++++++------------------------ 3 files changed, 430 insertions(+), 390 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index f4887a8aa0c7d..d81a0f95bdcd7 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -11,7 +11,7 @@ module.exports = { // Stop ESLint from looking for a configuration file in parent folders root: true, - plugins: ['jest', 'no-for-of-loops', 'react'], + plugins: ['jest', 'no-for-of-loops', 'react', 'prettier'], parser: 'babel-eslint', parserOptions: { @@ -82,6 +82,8 @@ module.exports = { // Prevent for...of loops because they require a Symbol polyfill. // You can disable this rule for code that isn't shipped (e.g. build scripts and tests). 'no-for-of-loops/no-for-of-loops': ERROR, + + 'prettier/prettier': ERROR, }, overrides: [ diff --git a/package.json b/package.json index 7467478fef91a..e50bd2d4a28db 100644 --- a/package.json +++ b/package.json @@ -25,23 +25,24 @@ }, "devDependencies": { "@babel/core": "^7.10.4", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^10.3.0", + "@testing-library/jest-dom": "^5.11.0", + "@testing-library/react": "^10.4.5", "babel-eslint": "^10.1.0", - "babel-jest": "^26.0.1", + "babel-jest": "^26.1.0", "babel-preset-react-app": "^9.1.2", "confusing-browser-globals": "^1.0.9", - "eslint": "^7.3.1", + "eslint": "^7.4.0", "eslint-config-fbjs": "^1.1.1", "eslint-config-prettier": "^6.11.0", - "eslint-plugin-babel": "^5.3.0", - "eslint-plugin-flowtype": "^5.1.3", - "eslint-plugin-jest": "^23.17.1", + "eslint-plugin-babel": "^5.3.1", + "eslint-plugin-flowtype": "^5.2.0", + "eslint-plugin-jest": "^23.18.0", "eslint-plugin-no-for-of-loops": "^1.0.1", - "eslint-plugin-react": "^7.20.0", - "flow-bin": "^0.128.0", + "eslint-plugin-prettier": "^3.1.4", + "eslint-plugin-react": "^7.20.3", + "flow-bin": "^0.129.0", "identity-obj-proxy": "^3.0.0", - "jest": "^26.0.1", + "jest": "^26.1.0", "parcel": "2.0.0-beta.1", "postcss-modules": "^2.0.0", "prettier": "1.19.1" diff --git a/yarn.lock b/yarn.lock index 650b64ba7697d..dd91760f237a6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2379,7 +2379,7 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-transform-typescript" "^7.9.0" -"@babel/runtime-corejs3@^7.10.2", "@babel/runtime-corejs3@^7.8.3": +"@babel/runtime-corejs3@^7.10.2": version "7.10.3" resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.10.3.tgz#931ed6941d3954924a7aa967ee440e60c507b91a" integrity sha512-HA7RPj5xvJxQl429r5Cxr2trJwOfPjKiqhCXcdQPSqO2G0RHPZpXu4fkYmBaTKCp2c/jRaMK9GB/lN+7zvvFPw== @@ -2401,6 +2401,13 @@ dependencies: regenerator-runtime "^0.13.4" +"@babel/runtime@^7.10.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.10.4.tgz#a6724f1a6b8d2f6ea5236dbfe58c7d7ea9c5eb99" + integrity sha512-UpTN5yUJr9b4EX2CnGNWIvER7Ab83ibv0pcvvHc4UOdrBI5jb8bj+32cCwPX6xu0mt2daFNjYhoi+X7beH0RSw== + dependencies: + regenerator-runtime "^0.13.4" + "@babel/template@^7.0.0", "@babel/template@^7.2.2", "@babel/template@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.7.4.tgz#428a7d9eecffe27deac0a98e23bf8e3675d2a77b" @@ -2542,103 +2549,103 @@ resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd" integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw== -"@jest/console@^26.0.1": - version "26.0.1" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-26.0.1.tgz#62b3b2fa8990f3cbffbef695c42ae9ddbc8f4b39" - integrity sha512-9t1KUe/93coV1rBSxMmBAOIK3/HVpwxArCA1CxskKyRiv6o8J70V8C/V3OJminVCTa2M0hQI9AWRd5wxu2dAHw== +"@jest/console@^26.1.0": + version "26.1.0" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-26.1.0.tgz#f67c89e4f4d04dbcf7b052aed5ab9c74f915b954" + integrity sha512-+0lpTHMd/8pJp+Nd4lyip+/Iyf2dZJvcCqrlkeZQoQid+JlThA4M9vxHtheyrQ99jJTMQam+es4BcvZ5W5cC3A== dependencies: - "@jest/types" "^26.0.1" + "@jest/types" "^26.1.0" chalk "^4.0.0" - jest-message-util "^26.0.1" - jest-util "^26.0.1" + jest-message-util "^26.1.0" + jest-util "^26.1.0" slash "^3.0.0" -"@jest/core@^26.0.1": - version "26.0.1" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-26.0.1.tgz#aa538d52497dfab56735efb00e506be83d841fae" - integrity sha512-Xq3eqYnxsG9SjDC+WLeIgf7/8KU6rddBxH+SCt18gEpOhAGYC/Mq+YbtlNcIdwjnnT+wDseXSbU0e5X84Y4jTQ== +"@jest/core@^26.1.0": + version "26.1.0" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-26.1.0.tgz#4580555b522de412a7998b3938c851e4f9da1c18" + integrity sha512-zyizYmDJOOVke4OO/De//aiv8b07OwZzL2cfsvWF3q9YssfpcKfcnZAwDY8f+A76xXSMMYe8i/f/LPocLlByfw== dependencies: - "@jest/console" "^26.0.1" - "@jest/reporters" "^26.0.1" - "@jest/test-result" "^26.0.1" - "@jest/transform" "^26.0.1" - "@jest/types" "^26.0.1" + "@jest/console" "^26.1.0" + "@jest/reporters" "^26.1.0" + "@jest/test-result" "^26.1.0" + "@jest/transform" "^26.1.0" + "@jest/types" "^26.1.0" ansi-escapes "^4.2.1" chalk "^4.0.0" exit "^0.1.2" graceful-fs "^4.2.4" - jest-changed-files "^26.0.1" - jest-config "^26.0.1" - jest-haste-map "^26.0.1" - jest-message-util "^26.0.1" + jest-changed-files "^26.1.0" + jest-config "^26.1.0" + jest-haste-map "^26.1.0" + jest-message-util "^26.1.0" jest-regex-util "^26.0.0" - jest-resolve "^26.0.1" - jest-resolve-dependencies "^26.0.1" - jest-runner "^26.0.1" - jest-runtime "^26.0.1" - jest-snapshot "^26.0.1" - jest-util "^26.0.1" - jest-validate "^26.0.1" - jest-watcher "^26.0.1" + jest-resolve "^26.1.0" + jest-resolve-dependencies "^26.1.0" + jest-runner "^26.1.0" + jest-runtime "^26.1.0" + jest-snapshot "^26.1.0" + jest-util "^26.1.0" + jest-validate "^26.1.0" + jest-watcher "^26.1.0" micromatch "^4.0.2" p-each-series "^2.1.0" rimraf "^3.0.0" slash "^3.0.0" strip-ansi "^6.0.0" -"@jest/environment@^26.0.1": - version "26.0.1" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-26.0.1.tgz#82f519bba71959be9b483675ee89de8c8f72a5c8" - integrity sha512-xBDxPe8/nx251u0VJ2dFAFz2H23Y98qdIaNwnMK6dFQr05jc+Ne/2np73lOAx+5mSBO/yuQldRrQOf6hP1h92g== +"@jest/environment@^26.1.0": + version "26.1.0" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-26.1.0.tgz#378853bcdd1c2443b4555ab908cfbabb851e96da" + integrity sha512-86+DNcGongbX7ai/KE/S3/NcUVZfrwvFzOOWX/W+OOTvTds7j07LtC+MgGydH5c8Ri3uIrvdmVgd1xFD5zt/xA== dependencies: - "@jest/fake-timers" "^26.0.1" - "@jest/types" "^26.0.1" - jest-mock "^26.0.1" + "@jest/fake-timers" "^26.1.0" + "@jest/types" "^26.1.0" + jest-mock "^26.1.0" -"@jest/fake-timers@^26.0.1": - version "26.0.1" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-26.0.1.tgz#f7aeff13b9f387e9d0cac9a8de3bba538d19d796" - integrity sha512-Oj/kCBnTKhm7CR+OJSjZty6N1bRDr9pgiYQr4wY221azLz5PHi08x/U+9+QpceAYOWheauLP8MhtSVFrqXQfhg== +"@jest/fake-timers@^26.1.0": + version "26.1.0" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-26.1.0.tgz#9a76b7a94c351cdbc0ad53e5a748789f819a65fe" + integrity sha512-Y5F3kBVWxhau3TJ825iuWy++BAuQzK/xEa+wD9vDH3RytW9f2DbMVodfUQC54rZDX3POqdxCgcKdgcOL0rYUpA== dependencies: - "@jest/types" "^26.0.1" + "@jest/types" "^26.1.0" "@sinonjs/fake-timers" "^6.0.1" - jest-message-util "^26.0.1" - jest-mock "^26.0.1" - jest-util "^26.0.1" + jest-message-util "^26.1.0" + jest-mock "^26.1.0" + jest-util "^26.1.0" -"@jest/globals@^26.0.1": - version "26.0.1" - resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-26.0.1.tgz#3f67b508a7ce62b6e6efc536f3d18ec9deb19a9c" - integrity sha512-iuucxOYB7BRCvT+TYBzUqUNuxFX1hqaR6G6IcGgEqkJ5x4htNKo1r7jk1ji9Zj8ZMiMw0oB5NaA7k5Tx6MVssA== +"@jest/globals@^26.1.0": + version "26.1.0" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-26.1.0.tgz#6cc5d7cbb79b76b120f2403d7d755693cf063ab1" + integrity sha512-MKiHPNaT+ZoG85oMaYUmGHEqu98y3WO2yeIDJrs2sJqHhYOy3Z6F7F/luzFomRQ8SQ1wEkmahFAz2291Iv8EAw== dependencies: - "@jest/environment" "^26.0.1" - "@jest/types" "^26.0.1" - expect "^26.0.1" + "@jest/environment" "^26.1.0" + "@jest/types" "^26.1.0" + expect "^26.1.0" -"@jest/reporters@^26.0.1": - version "26.0.1" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-26.0.1.tgz#14ae00e7a93e498cec35b0c00ab21c375d9b078f" - integrity sha512-NWWy9KwRtE1iyG/m7huiFVF9YsYv/e+mbflKRV84WDoJfBqUrNRyDbL/vFxQcYLl8IRqI4P3MgPn386x76Gf2g== +"@jest/reporters@^26.1.0": + version "26.1.0" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-26.1.0.tgz#08952e90c90282e14ff49e927bdf1873617dae78" + integrity sha512-SVAysur9FOIojJbF4wLP0TybmqwDkdnFxHSPzHMMIYyBtldCW9gG+Q5xWjpMFyErDiwlRuPyMSJSU64A67Pazg== dependencies: "@bcoe/v8-coverage" "^0.2.3" - "@jest/console" "^26.0.1" - "@jest/test-result" "^26.0.1" - "@jest/transform" "^26.0.1" - "@jest/types" "^26.0.1" + "@jest/console" "^26.1.0" + "@jest/test-result" "^26.1.0" + "@jest/transform" "^26.1.0" + "@jest/types" "^26.1.0" chalk "^4.0.0" collect-v8-coverage "^1.0.0" exit "^0.1.2" glob "^7.1.2" graceful-fs "^4.2.4" istanbul-lib-coverage "^3.0.0" - istanbul-lib-instrument "^4.0.0" + istanbul-lib-instrument "^4.0.3" istanbul-lib-report "^3.0.0" istanbul-lib-source-maps "^4.0.0" istanbul-reports "^3.0.2" - jest-haste-map "^26.0.1" - jest-resolve "^26.0.1" - jest-util "^26.0.1" - jest-worker "^26.0.0" + jest-haste-map "^26.1.0" + jest-resolve "^26.1.0" + jest-util "^26.1.0" + jest-worker "^26.1.0" slash "^3.0.0" source-map "^0.6.0" string-length "^4.0.1" @@ -2647,51 +2654,51 @@ optionalDependencies: node-notifier "^7.0.0" -"@jest/source-map@^26.0.0": - version "26.0.0" - resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-26.0.0.tgz#fd7706484a7d3faf7792ae29783933bbf48a4749" - integrity sha512-S2Z+Aj/7KOSU2TfW0dyzBze7xr95bkm5YXNUqqCek+HE0VbNNSNzrRwfIi5lf7wvzDTSS0/ib8XQ1krFNyYgbQ== +"@jest/source-map@^26.1.0": + version "26.1.0" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-26.1.0.tgz#a6a020d00e7d9478f4b690167c5e8b77e63adb26" + integrity sha512-XYRPYx4eEVX15cMT9mstnO7hkHP3krNtKfxUYd8L7gbtia8JvZZ6bMzSwa6IQJENbudTwKMw5R1BePRD+bkEmA== dependencies: callsites "^3.0.0" graceful-fs "^4.2.4" source-map "^0.6.0" -"@jest/test-result@^26.0.1": - version "26.0.1" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-26.0.1.tgz#1ffdc1ba4bc289919e54b9414b74c9c2f7b2b718" - integrity sha512-oKwHvOI73ICSYRPe8WwyYPTtiuOAkLSbY8/MfWF3qDEd/sa8EDyZzin3BaXTqufir/O/Gzea4E8Zl14XU4Mlyg== +"@jest/test-result@^26.1.0": + version "26.1.0" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-26.1.0.tgz#a93fa15b21ad3c7ceb21c2b4c35be2e407d8e971" + integrity sha512-Xz44mhXph93EYMA8aYDz+75mFbarTV/d/x0yMdI3tfSRs/vh4CqSxgzVmCps1fPkHDCtn0tU8IH9iCKgGeGpfw== dependencies: - "@jest/console" "^26.0.1" - "@jest/types" "^26.0.1" + "@jest/console" "^26.1.0" + "@jest/types" "^26.1.0" "@types/istanbul-lib-coverage" "^2.0.0" collect-v8-coverage "^1.0.0" -"@jest/test-sequencer@^26.0.1": - version "26.0.1" - resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-26.0.1.tgz#b0563424728f3fe9e75d1442b9ae4c11da73f090" - integrity sha512-ssga8XlwfP8YjbDcmVhwNlrmblddMfgUeAkWIXts1V22equp2GMIHxm7cyeD5Q/B0ZgKPK/tngt45sH99yLLGg== +"@jest/test-sequencer@^26.1.0": + version "26.1.0" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-26.1.0.tgz#41a6fc8b850c3f33f48288ea9ea517c047e7f14e" + integrity sha512-Z/hcK+rTq56E6sBwMoQhSRDVjqrGtj1y14e2bIgcowARaIE1SgOanwx6gvY4Q9gTKMoZQXbXvptji+q5GYxa6Q== dependencies: - "@jest/test-result" "^26.0.1" + "@jest/test-result" "^26.1.0" graceful-fs "^4.2.4" - jest-haste-map "^26.0.1" - jest-runner "^26.0.1" - jest-runtime "^26.0.1" + jest-haste-map "^26.1.0" + jest-runner "^26.1.0" + jest-runtime "^26.1.0" -"@jest/transform@^26.0.1": - version "26.0.1" - resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-26.0.1.tgz#0e3ecbb34a11cd4b2080ed0a9c4856cf0ceb0639" - integrity sha512-pPRkVkAQ91drKGbzCfDOoHN838+FSbYaEAvBXvKuWeeRRUD8FjwXkqfUNUZL6Ke48aA/1cqq/Ni7kVMCoqagWA== +"@jest/transform@^26.1.0": + version "26.1.0" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-26.1.0.tgz#697f48898c2a2787c9b4cb71d09d7e617464e509" + integrity sha512-ICPm6sUXmZJieq45ix28k0s+d/z2E8CHDsq+WwtWI6kW8m7I8kPqarSEcUN86entHQ570ZBRci5OWaKL0wlAWw== dependencies: "@babel/core" "^7.1.0" - "@jest/types" "^26.0.1" + "@jest/types" "^26.1.0" babel-plugin-istanbul "^6.0.0" chalk "^4.0.0" convert-source-map "^1.4.0" fast-json-stable-stringify "^2.0.0" graceful-fs "^4.2.4" - jest-haste-map "^26.0.1" + jest-haste-map "^26.1.0" jest-regex-util "^26.0.0" - jest-util "^26.0.1" + jest-util "^26.1.0" micromatch "^4.0.2" pirates "^4.0.1" slash "^3.0.0" @@ -2708,10 +2715,10 @@ "@types/yargs" "^15.0.0" chalk "^3.0.0" -"@jest/types@^26.0.1": - version "26.0.1" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.0.1.tgz#b78333fbd113fa7aec8d39de24f88de8686dac67" - integrity sha512-IbtjvqI9+eS1qFnOIEL7ggWmT+iK/U+Vde9cGWtYb/b6XgKb3X44ZAe/z9YZzoAAZ/E92m0DqrilF934IGNnQA== +"@jest/types@^26.1.0": + version "26.1.0" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.1.0.tgz#f8afaaaeeb23b5cad49dd1f7779689941dcb6057" + integrity sha512-GXigDDsp6ZlNMhXQDeuy/iYCDsRIHJabWtDzvnn36+aqFfG14JmFV0e/iXxY4SP9vbXSiPNOWdehU5MeqrYHBQ== dependencies: "@types/istanbul-lib-coverage" "^2.0.0" "@types/istanbul-reports" "^1.1.1" @@ -3503,23 +3510,25 @@ dependencies: "@sinonjs/commons" "^1.7.0" -"@testing-library/dom@^7.14.2": - version "7.16.2" - resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-7.16.2.tgz#f7a20b5548817e5c7ed26077913372d977be90af" - integrity sha512-4fT5l5L+5gfNhUZVCg0wnSszbRJ7A1ZHEz32v7OzH3mcY5lUsK++brI3IB2L9F5zO4kSDc2TRGEVa8v2hgl9vA== +"@testing-library/dom@^7.17.1": + version "7.20.0" + resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-7.20.0.tgz#2bab85e90f0221a56256c5d4741c2a36b7c45f4d" + integrity sha512-TywaC+qDGm/Ro34kRYkFQPdT+pxSF4UjZGLIqcGfFQH5IGR43Y7sGLPnkieIW/GNsu337oxNsLUAgpI0JWhXHw== dependencies: - "@babel/runtime" "^7.10.2" - aria-query "^4.0.2" + "@babel/runtime" "^7.10.3" + "@types/aria-query" "^4.2.0" + aria-query "^4.2.2" dom-accessibility-api "^0.4.5" pretty-format "^25.5.0" -"@testing-library/jest-dom@^5.10.1": - version "5.10.1" - resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.10.1.tgz#6508a9f007bd74e5d3c0b3135b668027ab663989" - integrity sha512-uv9lLAnEFRzwUTN/y9lVVXVXlEzazDkelJtM5u92PsGkEasmdI+sfzhZHxSDzlhZVTrlLfuMh2safMr8YmzXLg== +"@testing-library/jest-dom@^5.11.0": + version "5.11.0" + resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.11.0.tgz#1439f08dc85ce7c6d3bbad0ee5d53b2206f55768" + integrity sha512-mhaCySy7dZlyfcxcYy+0jLllODHEiHkVdmwQ00wD0HrWiSx0fSVHz/0WmdlRkvhfSOuqsRsBUreXOtBvruWGQA== dependencies: "@babel/runtime" "^7.9.2" "@types/testing-library__jest-dom" "^5.9.1" + aria-query "^4.2.2" chalk "^3.0.0" css "^2.2.4" css.escape "^1.5.1" @@ -3528,15 +3537,21 @@ lodash "^4.17.15" redent "^3.0.0" -"@testing-library/react@^10.3.0": - version "10.3.0" - resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-10.3.0.tgz#d615385b8d86ef4d76142a423755d471b3673295" - integrity sha512-Rhn5uJK6lYHWzlGVbK6uAvheAW8AUoFYxTLGdDxgsJDaK/PYy5drWfW/6YpMMOKMw+u6jHHl4MNHlt5qLHnm0Q== +"@testing-library/react@^10.4.5": + version "10.4.5" + resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-10.4.5.tgz#e66e004d6beb60a26b4e5d4e4d9989738d7077f3" + integrity sha512-M5A0W4VphBiEm4vgnq7vHC+/e4Bp/3iIOAWap1FtIiA+Zom6BtXpY3RSTOqc8bZsCcu9gFBZ/lxaiMW6uJddWg== dependencies: - "@babel/runtime" "^7.10.2" - "@testing-library/dom" "^7.14.2" + "@babel/runtime" "^7.10.3" + "@testing-library/dom" "^7.17.1" + semver "^7.3.2" -"@types/babel__core@^7.1.7": +"@types/aria-query@^4.2.0": + version "4.2.0" + resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-4.2.0.tgz#14264692a9d6e2fa4db3df5e56e94b5e25647ac0" + integrity sha512-iIgQNzCm0v7QMhhe4Jjn9uRh+I6GoPmt03CbEtwx3ao8/EfoQcmgtqH4vQ5Db/lxiIGaWDv6nwvunuh0RyX0+A== + +"@types/babel__core@^7.0.0", "@types/babel__core@^7.1.7": version "7.1.9" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.9.tgz#77e59d438522a6fb898fa43dc3455c6e72f3963d" integrity sha512-sY2RsIJ5rpER1u3/aQ8OFSI7qGIy8o1NEEbgb2UaJcvOtXOMpd39ko723NBpjQFg9SIX7TXtjejZVGeIMLhoOw== @@ -3852,7 +3867,7 @@ argparse@^1.0.7: dependencies: sprintf-js "~1.0.2" -aria-query@^4.0.2: +aria-query@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-4.2.2.tgz#0d2ca6c9aceb56b8977e9fed6aed7e15bbd2f83b" integrity sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA== @@ -3904,6 +3919,15 @@ array-unique@^0.3.2: resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= +array.prototype.flatmap@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.2.3.tgz#1c13f84a178566042dd63de4414440db9222e443" + integrity sha512-OOEk+lkePcg+ODXIpvuU9PAryCikCJyo7GlDG1upleEpQRx6mzL9puEBkozQ5iAx20KV0l3DbyQwqciJtqe5Pg== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" + function-bind "^1.1.1" + asn1.js@^4.0.0: version "4.10.1" resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" @@ -3994,16 +4018,16 @@ babel-eslint@^10.1.0: eslint-visitor-keys "^1.0.0" resolve "^1.12.0" -babel-jest@^26.0.1: - version "26.0.1" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-26.0.1.tgz#450139ce4b6c17174b136425bda91885c397bc46" - integrity sha512-Z4GGmSNQ8pX3WS1O+6v3fo41YItJJZsVxG5gIQ+HuB/iuAQBJxMTHTwz292vuYws1LnHfwSRgoqI+nxdy/pcvw== +babel-jest@^26.1.0: + version "26.1.0" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-26.1.0.tgz#b20751185fc7569a0f135730584044d1cb934328" + integrity sha512-Nkqgtfe7j6PxLO6TnCQQlkMm8wdTdnIF8xrdpooHCuD5hXRzVEPbPneTJKknH5Dsv3L8ip9unHDAp48YQ54Dkg== dependencies: - "@jest/transform" "^26.0.1" - "@jest/types" "^26.0.1" + "@jest/transform" "^26.1.0" + "@jest/types" "^26.1.0" "@types/babel__core" "^7.1.7" babel-plugin-istanbul "^6.0.0" - babel-preset-jest "^26.0.0" + babel-preset-jest "^26.1.0" chalk "^4.0.0" graceful-fs "^4.2.4" slash "^3.0.0" @@ -4033,13 +4057,14 @@ babel-plugin-istanbul@^6.0.0: istanbul-lib-instrument "^4.0.0" test-exclude "^6.0.0" -babel-plugin-jest-hoist@^26.0.0: - version "26.0.0" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.0.0.tgz#fd1d35f95cf8849fc65cb01b5e58aedd710b34a8" - integrity sha512-+AuoehOrjt9irZL7DOt2+4ZaTM6dlu1s5TTS46JBa0/qem4dy7VNW3tMb96qeEqcIh20LD73TVNtmVEeymTG7w== +babel-plugin-jest-hoist@^26.1.0: + version "26.1.0" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.1.0.tgz#c6a774da08247a28285620a64dfadbd05dd5233a" + integrity sha512-qhqLVkkSlqmC83bdMhM8WW4Z9tB+JkjqAqlbbohS9sJLT5Ha2vfzuKqg5yenXrAjOPG2YC0WiXdH3a9PvB+YYw== dependencies: "@babel/template" "^7.3.3" "@babel/types" "^7.3.3" + "@types/babel__core" "^7.0.0" "@types/babel__traverse" "^7.0.6" babel-plugin-macros@2.8.0: @@ -4073,12 +4098,12 @@ babel-preset-current-node-syntax@^0.1.2: "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" "@babel/plugin-syntax-optional-chaining" "^7.8.3" -babel-preset-jest@^26.0.0: - version "26.0.0" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-26.0.0.tgz#1eac82f513ad36c4db2e9263d7c485c825b1faa6" - integrity sha512-9ce+DatAa31DpR4Uir8g4Ahxs5K4W4L8refzt+qHWQANb6LhGcAEfIFgLUwk67oya2cCUd6t4eUMtO/z64ocNw== +babel-preset-jest@^26.1.0: + version "26.1.0" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-26.1.0.tgz#612f714e5b457394acfd863793c564cbcdb7d1c1" + integrity sha512-na9qCqFksknlEj5iSdw1ehMVR06LCCTkZLGKeEtxDDdhg8xpUF09m29Kvh1pRbZ07h7AQ5ttLYUwpXL4tO6w7w== dependencies: - babel-plugin-jest-hoist "^26.0.0" + babel-plugin-jest-hoist "^26.1.0" babel-preset-current-node-syntax "^0.1.2" babel-preset-react-app@^9.1.2: @@ -5410,25 +5435,25 @@ eslint-config-prettier@^6.11.0: dependencies: get-stdin "^6.0.0" -eslint-plugin-babel@^5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-babel/-/eslint-plugin-babel-5.3.0.tgz#2e7f251ccc249326da760c1a4c948a91c32d0023" - integrity sha512-HPuNzSPE75O+SnxHIafbW5QB45r2w78fxqwK3HmjqIUoPfPzVrq6rD+CINU3yzoDSzEhUkX07VUphbF73Lth/w== +eslint-plugin-babel@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-babel/-/eslint-plugin-babel-5.3.1.tgz#75a2413ffbf17e7be57458301c60291f2cfbf560" + integrity sha512-VsQEr6NH3dj664+EyxJwO4FCYm/00JhYb3Sk3ft8o+fpKuIfQ9TaW6uVUfvwMXHcf/lsnRIoyFPsLMyiWCSL/g== dependencies: eslint-rule-composer "^0.3.0" -eslint-plugin-flowtype@^5.1.3: - version "5.1.3" - resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-5.1.3.tgz#0c63694463b0e8b296975649d637dd39fdf9e877" - integrity sha512-UU+BbIxBflqJ171yxbd/HcOktCmOdhXbchIVIq/yBvKpLZXvfzNDOyJGcnuQYLaH840hdoIdU/bqxhoW6I0rIQ== +eslint-plugin-flowtype@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-5.2.0.tgz#a4bef5dc18f9b2bdb41569a4ab05d73805a3d261" + integrity sha512-z7ULdTxuhlRJcEe1MVljePXricuPOrsWfScRXFhNzVD5dmTHWjIF57AxD0e7AbEoLSbjSsaA5S+hCg43WvpXJQ== dependencies: lodash "^4.17.15" string-natural-compare "^3.0.1" -eslint-plugin-jest@^23.17.1: - version "23.17.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-23.17.1.tgz#c0f39ba78e0f33b7ee1ce4ec92b773e39026ea3f" - integrity sha512-/o36fw67qNbJGWbSBIBMfseMsNP/d88WUHAGHCi1xFwsNB3XXZGdvxbOw49j3iQz6MCW/yw8OeOsuQhi6mM5ZA== +eslint-plugin-jest@^23.18.0: + version "23.18.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-23.18.0.tgz#4813eacb181820ed13c5505f400956d176b25af8" + integrity sha512-wLPM/Rm1SGhxrFQ2TKM/BYsYPhn7ch6ZEK92S2o/vGkAAnDXM0I4nTIo745RIX+VlCRMFgBuJEax6XfTHMdeKg== dependencies: "@typescript-eslint/experimental-utils" "^2.5.0" @@ -5437,22 +5462,29 @@ eslint-plugin-no-for-of-loops@^1.0.1: resolved "https://registry.yarnpkg.com/eslint-plugin-no-for-of-loops/-/eslint-plugin-no-for-of-loops-1.0.1.tgz#2ee3732d50c642b8d1bfacedbfe3b28f86222369" integrity sha512-uCotzBHt2W+HbLw2srRmqDJHOPbJGzeVLstKh8YyxS3ppduq2P50qdpJfHKoD+UGbnqA/zhy8NRgPH6p0y8bnA== -eslint-plugin-react@^7.20.0: - version "7.20.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.20.0.tgz#f98712f0a5e57dfd3e5542ef0604b8739cd47be3" - integrity sha512-rqe1abd0vxMjmbPngo4NaYxTcR3Y4Hrmc/jg4T+sYz63yqlmJRknpEQfmWY+eDWPuMmix6iUIK+mv0zExjeLgA== +eslint-plugin-prettier@^3.1.4: + version "3.1.4" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.4.tgz#168ab43154e2ea57db992a2cd097c828171f75c2" + integrity sha512-jZDa8z76klRqo+TdGDTFJSavwbnWK2ZpqGKNZ+VvweMW516pDUMmQ2koXvxEE4JhzNvTv+radye/bWGBmA6jmg== + dependencies: + prettier-linter-helpers "^1.0.0" + +eslint-plugin-react@^7.20.3: + version "7.20.3" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.20.3.tgz#0590525e7eb83890ce71f73c2cf836284ad8c2f1" + integrity sha512-txbo090buDeyV0ugF3YMWrzLIUqpYTsWSDZV9xLSmExE1P/Kmgg9++PD931r+KEWS66O1c9R4srLVVHmeHpoAg== dependencies: array-includes "^3.1.1" + array.prototype.flatmap "^1.2.3" doctrine "^2.1.0" has "^1.0.3" - jsx-ast-utils "^2.2.3" - object.entries "^1.1.1" + jsx-ast-utils "^2.4.1" + object.entries "^1.1.2" object.fromentries "^2.0.2" object.values "^1.1.1" prop-types "^15.7.2" - resolve "^1.15.1" + resolve "^1.17.0" string.prototype.matchall "^4.0.2" - xregexp "^4.3.0" eslint-rule-composer@^0.3.0: version "0.3.0" @@ -5479,10 +5511,10 @@ eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.2 resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== -eslint@^7.3.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.3.1.tgz#76392bd7e44468d046149ba128d1566c59acbe19" - integrity sha512-cQC/xj9bhWUcyi/RuMbRtC3I0eW8MH0jhRELSvpKYkWep3C6YZ2OkvcvJVUeO6gcunABmzptbXBuDoXsjHmfTA== +eslint@^7.4.0: + version "7.4.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.4.0.tgz#4e35a2697e6c1972f9d6ef2b690ad319f80f206f" + integrity sha512-gU+lxhlPHu45H3JkEGgYhWhkR9wLHHEXC9FbWFnTlEkbKyZKWgWRLgf61E8zWmBuI6g5xKBph9ltg3NtZMVF8g== dependencies: "@babel/code-frame" "^7.0.0" ajv "^6.10.0" @@ -5653,16 +5685,16 @@ expand-brackets@^2.1.4: snapdragon "^0.8.1" to-regex "^3.0.1" -expect@^26.0.1: - version "26.0.1" - resolved "https://registry.yarnpkg.com/expect/-/expect-26.0.1.tgz#18697b9611a7e2725e20ba3ceadda49bc9865421" - integrity sha512-QcCy4nygHeqmbw564YxNbHTJlXh47dVID2BUP52cZFpLU9zHViMFK6h07cC1wf7GYCTIigTdAXhVua8Yl1FkKg== +expect@^26.1.0: + version "26.1.0" + resolved "https://registry.yarnpkg.com/expect/-/expect-26.1.0.tgz#8c62e31d0f8d5a8ebb186ee81473d15dd2fbf7c8" + integrity sha512-QbH4LZXDsno9AACrN9eM0zfnby9G+OsdNgZUohjg/P0mLy1O+/bzTAJGT6VSIjVCe8yKM6SzEl/ckEOFBT7Vnw== dependencies: - "@jest/types" "^26.0.1" + "@jest/types" "^26.1.0" ansi-styles "^4.0.0" jest-get-type "^26.0.0" - jest-matcher-utils "^26.0.1" - jest-message-util "^26.0.1" + jest-matcher-utils "^26.1.0" + jest-message-util "^26.1.0" jest-regex-util "^26.0.0" extend-shallow@^2.0.1: @@ -5719,6 +5751,11 @@ fast-deep-equal@^3.1.1: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== +fast-diff@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" + integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== + fast-glob@3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.1.1.tgz#87ee30e9e9f3eb40d6f254a7997655da753d7c82" @@ -5851,10 +5888,10 @@ flatted@^2.0.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== -flow-bin@^0.128.0: - version "0.128.0" - resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.128.0.tgz#fd1232a64dc46874d8d499f16a1934b964f4c2ae" - integrity sha512-EnmMSOCrkx8F0r1+T1d1HODQ+ddy5yRfkT3CvwmK05IWZyXQy27OVdNwdXUWRqc0iMW75T4QkoXaVBYrMqfk+A== +flow-bin@^0.129.0: + version "0.129.0" + resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.129.0.tgz#50294d6e335dd97d095c27b096ea0b94c2415d55" + integrity sha512-WLXOj09oCK6nODVKM5uxvAzBpxXeI304E60tELMeQd/TJsyfbykNCZ+e4xml9eUOyoac9nDL3YrJpPZMzq0tMA== follow-redirects@^1.0.0: version "1.9.0" @@ -6702,7 +6739,7 @@ istanbul-lib-coverage@^3.0.0: resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz#f5944a37c70b550b02a78a5c3b2055b280cec8ec" integrity sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg== -istanbul-lib-instrument@^4.0.0: +istanbul-lib-instrument@^4.0.0, istanbul-lib-instrument@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz#873c6fff897450118222774696a3f28902d77c1d" integrity sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ== @@ -6738,57 +6775,57 @@ istanbul-reports@^3.0.2: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" -jest-changed-files@^26.0.1: - version "26.0.1" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-26.0.1.tgz#1334630c6a1ad75784120f39c3aa9278e59f349f" - integrity sha512-q8LP9Sint17HaE2LjxQXL+oYWW/WeeXMPE2+Op9X3mY8IEGFVc14xRxFjUuXUbcPAlDLhtWdIEt59GdQbn76Hw== +jest-changed-files@^26.1.0: + version "26.1.0" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-26.1.0.tgz#de66b0f30453bca2aff98e9400f75905da495305" + integrity sha512-HS5MIJp3B8t0NRKGMCZkcDUZo36mVRvrDETl81aqljT1S9tqiHRSpyoOvWg9ZilzZG9TDisDNaN1IXm54fLRZw== dependencies: - "@jest/types" "^26.0.1" + "@jest/types" "^26.1.0" execa "^4.0.0" throat "^5.0.0" -jest-cli@^26.0.1: - version "26.0.1" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-26.0.1.tgz#3a42399a4cbc96a519b99ad069a117d955570cac" - integrity sha512-pFLfSOBcbG9iOZWaMK4Een+tTxi/Wcm34geqZEqrst9cZDkTQ1LZ2CnBrTlHWuYAiTMFr0EQeK52ScyFU8wK+w== +jest-cli@^26.1.0: + version "26.1.0" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-26.1.0.tgz#eb9ec8a18cf3b6aa556d9deaa9e24be12b43ad87" + integrity sha512-Imumvjgi3rU7stq6SJ1JUEMaV5aAgJYXIs0jPqdUnF47N/Tk83EXfmtvNKQ+SnFVI6t6mDOvfM3aA9Sg6kQPSw== dependencies: - "@jest/core" "^26.0.1" - "@jest/test-result" "^26.0.1" - "@jest/types" "^26.0.1" + "@jest/core" "^26.1.0" + "@jest/test-result" "^26.1.0" + "@jest/types" "^26.1.0" chalk "^4.0.0" exit "^0.1.2" graceful-fs "^4.2.4" import-local "^3.0.2" is-ci "^2.0.0" - jest-config "^26.0.1" - jest-util "^26.0.1" - jest-validate "^26.0.1" + jest-config "^26.1.0" + jest-util "^26.1.0" + jest-validate "^26.1.0" prompts "^2.0.1" yargs "^15.3.1" -jest-config@^26.0.1: - version "26.0.1" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-26.0.1.tgz#096a3d4150afadf719d1fab00e9a6fb2d6d67507" - integrity sha512-9mWKx2L1LFgOXlDsC4YSeavnblN6A4CPfXFiobq+YYLaBMymA/SczN7xYTSmLaEYHZOcB98UdoN4m5uNt6tztg== +jest-config@^26.1.0: + version "26.1.0" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-26.1.0.tgz#9074f7539acc185e0113ad6d22ed589c16a37a73" + integrity sha512-ONTGeoMbAwGCdq4WuKkMcdMoyfs5CLzHEkzFOlVvcDXufZSaIWh/OXMLa2fwKXiOaFcqEw8qFr4VOKJQfn4CVw== dependencies: "@babel/core" "^7.1.0" - "@jest/test-sequencer" "^26.0.1" - "@jest/types" "^26.0.1" - babel-jest "^26.0.1" + "@jest/test-sequencer" "^26.1.0" + "@jest/types" "^26.1.0" + babel-jest "^26.1.0" chalk "^4.0.0" deepmerge "^4.2.2" glob "^7.1.1" graceful-fs "^4.2.4" - jest-environment-jsdom "^26.0.1" - jest-environment-node "^26.0.1" + jest-environment-jsdom "^26.1.0" + jest-environment-node "^26.1.0" jest-get-type "^26.0.0" - jest-jasmine2 "^26.0.1" + jest-jasmine2 "^26.1.0" jest-regex-util "^26.0.0" - jest-resolve "^26.0.1" - jest-util "^26.0.1" - jest-validate "^26.0.1" + jest-resolve "^26.1.0" + jest-util "^26.1.0" + jest-validate "^26.1.0" micromatch "^4.0.2" - pretty-format "^26.0.1" + pretty-format "^26.1.0" jest-diff@^25.1.0, jest-diff@^25.2.1, jest-diff@^25.5.0: version "25.5.0" @@ -6800,15 +6837,15 @@ jest-diff@^25.1.0, jest-diff@^25.2.1, jest-diff@^25.5.0: jest-get-type "^25.2.6" pretty-format "^25.5.0" -jest-diff@^26.0.1: - version "26.0.1" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-26.0.1.tgz#c44ab3cdd5977d466de69c46929e0e57f89aa1de" - integrity sha512-odTcHyl5X+U+QsczJmOjWw5tPvww+y9Yim5xzqxVl/R1j4z71+fHW4g8qu1ugMmKdFdxw+AtQgs5mupPnzcIBQ== +jest-diff@^26.1.0: + version "26.1.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-26.1.0.tgz#00a549bdc936c9691eb4dc25d1fbd78bf456abb2" + integrity sha512-GZpIcom339y0OXznsEKjtkfKxNdg7bVbEofK8Q6MnevTIiR1jNhDWKhRX6X0SDXJlwn3dy59nZ1z55fLkAqPWg== dependencies: chalk "^4.0.0" diff-sequences "^26.0.0" jest-get-type "^26.0.0" - pretty-format "^26.0.1" + pretty-format "^26.1.0" jest-docblock@^26.0.0: version "26.0.0" @@ -6817,39 +6854,39 @@ jest-docblock@^26.0.0: dependencies: detect-newline "^3.0.0" -jest-each@^26.0.1: - version "26.0.1" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-26.0.1.tgz#633083061619302fc90dd8f58350f9d77d67be04" - integrity sha512-OTgJlwXCAR8NIWaXFL5DBbeS4QIYPuNASkzSwMCJO+ywo9BEa6TqkaSWsfR7VdbMLdgYJqSfQcIyjJCNwl5n4Q== +jest-each@^26.1.0: + version "26.1.0" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-26.1.0.tgz#e35449875009a22d74d1bda183b306db20f286f7" + integrity sha512-lYiSo4Igr81q6QRsVQq9LIkJW0hZcKxkIkHzNeTMPENYYDw/W/Raq28iJ0sLlNFYz2qxxeLnc5K2gQoFYlu2bA== dependencies: - "@jest/types" "^26.0.1" + "@jest/types" "^26.1.0" chalk "^4.0.0" jest-get-type "^26.0.0" - jest-util "^26.0.1" - pretty-format "^26.0.1" - -jest-environment-jsdom@^26.0.1: - version "26.0.1" - resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-26.0.1.tgz#217690852e5bdd7c846a4e3b50c8ffd441dfd249" - integrity sha512-u88NJa3aptz2Xix2pFhihRBAatwZHWwSiRLBDBQE1cdJvDjPvv7ZGA0NQBxWwDDn7D0g1uHqxM8aGgfA9Bx49g== - dependencies: - "@jest/environment" "^26.0.1" - "@jest/fake-timers" "^26.0.1" - "@jest/types" "^26.0.1" - jest-mock "^26.0.1" - jest-util "^26.0.1" + jest-util "^26.1.0" + pretty-format "^26.1.0" + +jest-environment-jsdom@^26.1.0: + version "26.1.0" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-26.1.0.tgz#9dc7313ffe1b59761dad1fedb76e2503e5d37c5b" + integrity sha512-dWfiJ+spunVAwzXbdVqPH1LbuJW/kDL+FyqgA5YzquisHqTi0g9hquKif9xKm7c1bKBj6wbmJuDkeMCnxZEpUw== + dependencies: + "@jest/environment" "^26.1.0" + "@jest/fake-timers" "^26.1.0" + "@jest/types" "^26.1.0" + jest-mock "^26.1.0" + jest-util "^26.1.0" jsdom "^16.2.2" -jest-environment-node@^26.0.1: - version "26.0.1" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-26.0.1.tgz#584a9ff623124ff6eeb49e0131b5f7612b310b13" - integrity sha512-4FRBWcSn5yVo0KtNav7+5NH5Z/tEgDLp7VRQVS5tCouWORxj+nI+1tOLutM07Zb2Qi7ja+HEDoOUkjBSWZg/IQ== +jest-environment-node@^26.1.0: + version "26.1.0" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-26.1.0.tgz#8bb387b3eefb132eab7826f9a808e4e05618960b" + integrity sha512-DNm5x1aQH0iRAe9UYAkZenuzuJ69VKzDCAYISFHQ5i9e+2Tbeu2ONGY7YStubCLH8a1wdKBgqScYw85+ySxqxg== dependencies: - "@jest/environment" "^26.0.1" - "@jest/fake-timers" "^26.0.1" - "@jest/types" "^26.0.1" - jest-mock "^26.0.1" - jest-util "^26.0.1" + "@jest/environment" "^26.1.0" + "@jest/fake-timers" "^26.1.0" + "@jest/types" "^26.1.0" + jest-mock "^26.1.0" + jest-util "^26.1.0" jest-get-type@^25.2.6: version "25.2.6" @@ -6861,19 +6898,19 @@ jest-get-type@^26.0.0: resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-26.0.0.tgz#381e986a718998dbfafcd5ec05934be538db4039" integrity sha512-zRc1OAPnnws1EVfykXOj19zo2EMw5Hi6HLbFCSjpuJiXtOWAYIjNsHVSbpQ8bDX7L5BGYGI8m+HmKdjHYFF0kg== -jest-haste-map@^26.0.1: - version "26.0.1" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-26.0.1.tgz#40dcc03c43ac94d25b8618075804d09cd5d49de7" - integrity sha512-J9kBl/EdjmDsvyv7CiyKY5+DsTvVOScenprz/fGqfLg/pm1gdjbwwQ98nW0t+OIt+f+5nAVaElvn/6wP5KO7KA== +jest-haste-map@^26.1.0: + version "26.1.0" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-26.1.0.tgz#ef31209be73f09b0d9445e7d213e1b53d0d1476a" + integrity sha512-WeBS54xCIz9twzkEdm6+vJBXgRBQfdbbXD0dk8lJh7gLihopABlJmIQFdWSDDtuDe4PRiObsjZSUjbJ1uhWEpA== dependencies: - "@jest/types" "^26.0.1" + "@jest/types" "^26.1.0" "@types/graceful-fs" "^4.1.2" anymatch "^3.0.3" fb-watchman "^2.0.0" graceful-fs "^4.2.4" - jest-serializer "^26.0.0" - jest-util "^26.0.1" - jest-worker "^26.0.0" + jest-serializer "^26.1.0" + jest-util "^26.1.0" + jest-worker "^26.1.0" micromatch "^4.0.2" sane "^4.0.3" walker "^1.0.7" @@ -6881,36 +6918,36 @@ jest-haste-map@^26.0.1: optionalDependencies: fsevents "^2.1.2" -jest-jasmine2@^26.0.1: - version "26.0.1" - resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-26.0.1.tgz#947c40ee816636ba23112af3206d6fa7b23c1c1c" - integrity sha512-ILaRyiWxiXOJ+RWTKupzQWwnPaeXPIoLS5uW41h18varJzd9/7I0QJGqg69fhTT1ev9JpSSo9QtalriUN0oqOg== +jest-jasmine2@^26.1.0: + version "26.1.0" + resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-26.1.0.tgz#4dfe349b2b2d3c6b3a27c024fd4cb57ac0ed4b6f" + integrity sha512-1IPtoDKOAG+MeBrKvvuxxGPJb35MTTRSDglNdWWCndCB3TIVzbLThRBkwH9P081vXLgiJHZY8Bz3yzFS803xqQ== dependencies: "@babel/traverse" "^7.1.0" - "@jest/environment" "^26.0.1" - "@jest/source-map" "^26.0.0" - "@jest/test-result" "^26.0.1" - "@jest/types" "^26.0.1" + "@jest/environment" "^26.1.0" + "@jest/source-map" "^26.1.0" + "@jest/test-result" "^26.1.0" + "@jest/types" "^26.1.0" chalk "^4.0.0" co "^4.6.0" - expect "^26.0.1" + expect "^26.1.0" is-generator-fn "^2.0.0" - jest-each "^26.0.1" - jest-matcher-utils "^26.0.1" - jest-message-util "^26.0.1" - jest-runtime "^26.0.1" - jest-snapshot "^26.0.1" - jest-util "^26.0.1" - pretty-format "^26.0.1" + jest-each "^26.1.0" + jest-matcher-utils "^26.1.0" + jest-message-util "^26.1.0" + jest-runtime "^26.1.0" + jest-snapshot "^26.1.0" + jest-util "^26.1.0" + pretty-format "^26.1.0" throat "^5.0.0" -jest-leak-detector@^26.0.1: - version "26.0.1" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-26.0.1.tgz#79b19ab3f41170e0a78eb8fa754a116d3447fb8c" - integrity sha512-93FR8tJhaYIWrWsbmVN1pQ9ZNlbgRpfvrnw5LmgLRX0ckOJ8ut/I35CL7awi2ecq6Ca4lL59bEK9hr7nqoHWPA== +jest-leak-detector@^26.1.0: + version "26.1.0" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-26.1.0.tgz#039c3a07ebcd8adfa984b6ac015752c35792e0a6" + integrity sha512-dsMnKF+4BVOZwvQDlgn3MG+Ns4JuLv8jNvXH56bgqrrboyCbI1rQg6EI5rs+8IYagVcfVP2yZFKfWNZy0rK0Hw== dependencies: jest-get-type "^26.0.0" - pretty-format "^26.0.1" + pretty-format "^26.1.0" jest-matcher-utils@^25.1.0: version "25.5.0" @@ -6922,23 +6959,23 @@ jest-matcher-utils@^25.1.0: jest-get-type "^25.2.6" pretty-format "^25.5.0" -jest-matcher-utils@^26.0.1: - version "26.0.1" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-26.0.1.tgz#12e1fc386fe4f14678f4cc8dbd5ba75a58092911" - integrity sha512-PUMlsLth0Azen8Q2WFTwnSkGh2JZ8FYuwijC8NR47vXKpsrKmA1wWvgcj1CquuVfcYiDEdj985u5Wmg7COEARw== +jest-matcher-utils@^26.1.0: + version "26.1.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-26.1.0.tgz#cf75a41bd413dda784f022de5a65a2a5c73a5c92" + integrity sha512-PW9JtItbYvES/xLn5mYxjMd+Rk+/kIt88EfH3N7w9KeOrHWaHrdYPnVHndGbsFGRJ2d5gKtwggCvkqbFDoouQA== dependencies: chalk "^4.0.0" - jest-diff "^26.0.1" + jest-diff "^26.1.0" jest-get-type "^26.0.0" - pretty-format "^26.0.1" + pretty-format "^26.1.0" -jest-message-util@^26.0.1: - version "26.0.1" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-26.0.1.tgz#07af1b42fc450b4cc8e90e4c9cef11b33ce9b0ac" - integrity sha512-CbK8uQREZ8umUfo8+zgIfEt+W7HAHjQCoRaNs4WxKGhAYBGwEyvxuK81FXa7VeB9pwDEXeeKOB2qcsNVCAvB7Q== +jest-message-util@^26.1.0: + version "26.1.0" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-26.1.0.tgz#52573fbb8f5cea443c4d1747804d7a238a3e233c" + integrity sha512-dY0+UlldiAJwNDJ08SF0HdF32g9PkbF2NRK/+2iMPU40O6q+iSn1lgog/u0UH8ksWoPv0+gNq8cjhYO2MFtT0g== dependencies: "@babel/code-frame" "^7.0.0" - "@jest/types" "^26.0.1" + "@jest/types" "^26.1.0" "@types/stack-utils" "^1.0.1" chalk "^4.0.0" graceful-fs "^4.2.4" @@ -6946,12 +6983,12 @@ jest-message-util@^26.0.1: slash "^3.0.0" stack-utils "^2.0.2" -jest-mock@^26.0.1: - version "26.0.1" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-26.0.1.tgz#7fd1517ed4955397cf1620a771dc2d61fad8fd40" - integrity sha512-MpYTBqycuPYSY6xKJognV7Ja46/TeRbAZept987Zp+tuJvMN0YBWyyhG9mXyYQaU3SBI0TUlSaO5L3p49agw7Q== +jest-mock@^26.1.0: + version "26.1.0" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-26.1.0.tgz#80d8286da1f05a345fbad1bfd6fa49a899465d3d" + integrity sha512-1Rm8EIJ3ZFA8yCIie92UbxZWj9SuVmUGcyhLHyAhY6WI3NIct38nVcfOPWhJteqSn8V8e3xOMha9Ojfazfpovw== dependencies: - "@jest/types" "^26.0.1" + "@jest/types" "^26.1.0" jest-pnp-resolver@^1.2.1: version "1.2.1" @@ -6963,165 +7000,165 @@ jest-regex-util@^26.0.0: resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-26.0.0.tgz#d25e7184b36e39fd466c3bc41be0971e821fee28" integrity sha512-Gv3ZIs/nA48/Zvjrl34bf+oD76JHiGDUxNOVgUjh3j890sblXryjY4rss71fPtD/njchl6PSE2hIhvyWa1eT0A== -jest-resolve-dependencies@^26.0.1: - version "26.0.1" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-26.0.1.tgz#607ba7ccc32151d185a477cff45bf33bce417f0b" - integrity sha512-9d5/RS/ft0vB/qy7jct/qAhzJsr6fRQJyGAFigK3XD4hf9kIbEH5gks4t4Z7kyMRhowU6HWm/o8ILqhaHdSqLw== +jest-resolve-dependencies@^26.1.0: + version "26.1.0" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-26.1.0.tgz#1ce36472f864a5dadf7dc82fa158e1c77955691b" + integrity sha512-fQVEPHHQ1JjHRDxzlLU/buuQ9om+hqW6Vo928aa4b4yvq4ZHBtRSDsLdKQLuCqn5CkTVpYZ7ARh2fbA8WkRE6g== dependencies: - "@jest/types" "^26.0.1" + "@jest/types" "^26.1.0" jest-regex-util "^26.0.0" - jest-snapshot "^26.0.1" + jest-snapshot "^26.1.0" -jest-resolve@^26.0.1: - version "26.0.1" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-26.0.1.tgz#21d1ee06f9ea270a343a8893051aeed940cde736" - integrity sha512-6jWxk0IKZkPIVTvq6s72RH735P8f9eCJW3IM5CX/SJFeKq1p2cZx0U49wf/SdMlhaB/anann5J2nCJj6HrbezQ== +jest-resolve@^26.1.0: + version "26.1.0" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-26.1.0.tgz#a530eaa302b1f6fa0479079d1561dd69abc00e68" + integrity sha512-KsY1JV9FeVgEmwIISbZZN83RNGJ1CC+XUCikf/ZWJBX/tO4a4NvA21YixokhdR9UnmPKKAC4LafVixJBrwlmfg== dependencies: - "@jest/types" "^26.0.1" + "@jest/types" "^26.1.0" chalk "^4.0.0" graceful-fs "^4.2.4" jest-pnp-resolver "^1.2.1" - jest-util "^26.0.1" + jest-util "^26.1.0" read-pkg-up "^7.0.1" resolve "^1.17.0" slash "^3.0.0" -jest-runner@^26.0.1: - version "26.0.1" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-26.0.1.tgz#ea03584b7ae4bacfb7e533d680a575a49ae35d50" - integrity sha512-CApm0g81b49Znm4cZekYQK67zY7kkB4umOlI2Dx5CwKAzdgw75EN+ozBHRvxBzwo1ZLYZ07TFxkaPm+1t4d8jA== +jest-runner@^26.1.0: + version "26.1.0" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-26.1.0.tgz#457f7fc522afe46ca6db1dccf19f87f500b3288d" + integrity sha512-elvP7y0fVDREnfqit0zAxiXkDRSw6dgCkzPCf1XvIMnSDZ8yogmSKJf192dpOgnUVykmQXwYYJnCx641uLTgcw== dependencies: - "@jest/console" "^26.0.1" - "@jest/environment" "^26.0.1" - "@jest/test-result" "^26.0.1" - "@jest/types" "^26.0.1" + "@jest/console" "^26.1.0" + "@jest/environment" "^26.1.0" + "@jest/test-result" "^26.1.0" + "@jest/types" "^26.1.0" chalk "^4.0.0" exit "^0.1.2" graceful-fs "^4.2.4" - jest-config "^26.0.1" + jest-config "^26.1.0" jest-docblock "^26.0.0" - jest-haste-map "^26.0.1" - jest-jasmine2 "^26.0.1" - jest-leak-detector "^26.0.1" - jest-message-util "^26.0.1" - jest-resolve "^26.0.1" - jest-runtime "^26.0.1" - jest-util "^26.0.1" - jest-worker "^26.0.0" + jest-haste-map "^26.1.0" + jest-jasmine2 "^26.1.0" + jest-leak-detector "^26.1.0" + jest-message-util "^26.1.0" + jest-resolve "^26.1.0" + jest-runtime "^26.1.0" + jest-util "^26.1.0" + jest-worker "^26.1.0" source-map-support "^0.5.6" throat "^5.0.0" -jest-runtime@^26.0.1: - version "26.0.1" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-26.0.1.tgz#a121a6321235987d294168e282d52b364d7d3f89" - integrity sha512-Ci2QhYFmANg5qaXWf78T2Pfo6GtmIBn2rRaLnklRyEucmPccmCKvS9JPljcmtVamsdMmkyNkVFb9pBTD6si9Lw== - dependencies: - "@jest/console" "^26.0.1" - "@jest/environment" "^26.0.1" - "@jest/fake-timers" "^26.0.1" - "@jest/globals" "^26.0.1" - "@jest/source-map" "^26.0.0" - "@jest/test-result" "^26.0.1" - "@jest/transform" "^26.0.1" - "@jest/types" "^26.0.1" +jest-runtime@^26.1.0: + version "26.1.0" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-26.1.0.tgz#45a37af42115f123ed5c51f126c05502da2469cb" + integrity sha512-1qiYN+EZLmG1QV2wdEBRf+Ci8i3VSfIYLF02U18PiUDrMbhfpN/EAMMkJtT02jgJUoaEOpHAIXG6zS3QRMzRmA== + dependencies: + "@jest/console" "^26.1.0" + "@jest/environment" "^26.1.0" + "@jest/fake-timers" "^26.1.0" + "@jest/globals" "^26.1.0" + "@jest/source-map" "^26.1.0" + "@jest/test-result" "^26.1.0" + "@jest/transform" "^26.1.0" + "@jest/types" "^26.1.0" "@types/yargs" "^15.0.0" chalk "^4.0.0" collect-v8-coverage "^1.0.0" exit "^0.1.2" glob "^7.1.3" graceful-fs "^4.2.4" - jest-config "^26.0.1" - jest-haste-map "^26.0.1" - jest-message-util "^26.0.1" - jest-mock "^26.0.1" + jest-config "^26.1.0" + jest-haste-map "^26.1.0" + jest-message-util "^26.1.0" + jest-mock "^26.1.0" jest-regex-util "^26.0.0" - jest-resolve "^26.0.1" - jest-snapshot "^26.0.1" - jest-util "^26.0.1" - jest-validate "^26.0.1" + jest-resolve "^26.1.0" + jest-snapshot "^26.1.0" + jest-util "^26.1.0" + jest-validate "^26.1.0" slash "^3.0.0" strip-bom "^4.0.0" yargs "^15.3.1" -jest-serializer@^26.0.0: - version "26.0.0" - resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-26.0.0.tgz#f6c521ddb976943b93e662c0d4d79245abec72a3" - integrity sha512-sQGXLdEGWFAE4wIJ2ZaIDb+ikETlUirEOBsLXdoBbeLhTHkZUJwgk3+M8eyFizhM6le43PDCCKPA1hzkSDo4cQ== +jest-serializer@^26.1.0: + version "26.1.0" + resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-26.1.0.tgz#72a394531fc9b08e173dc7d297440ac610d95022" + integrity sha512-eqZOQG/0+MHmr25b2Z86g7+Kzd5dG9dhCiUoyUNJPgiqi38DqbDEOlHcNijyfZoj74soGBohKBZuJFS18YTJ5w== dependencies: graceful-fs "^4.2.4" -jest-snapshot@^26.0.1: - version "26.0.1" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-26.0.1.tgz#1baa942bd83d47b837a84af7fcf5fd4a236da399" - integrity sha512-jxd+cF7+LL+a80qh6TAnTLUZHyQoWwEHSUFJjkw35u3Gx+BZUNuXhYvDqHXr62UQPnWo2P6fvQlLjsU93UKyxA== +jest-snapshot@^26.1.0: + version "26.1.0" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-26.1.0.tgz#c36ed1e0334bd7bd2fe5ad07e93a364ead7e1349" + integrity sha512-YhSbU7eMTVQO/iRbNs8j0mKRxGp4plo7sJ3GzOQ0IYjvsBiwg0T1o0zGQAYepza7lYHuPTrG5J2yDd0CE2YxSw== dependencies: "@babel/types" "^7.0.0" - "@jest/types" "^26.0.1" + "@jest/types" "^26.1.0" "@types/prettier" "^2.0.0" chalk "^4.0.0" - expect "^26.0.1" + expect "^26.1.0" graceful-fs "^4.2.4" - jest-diff "^26.0.1" + jest-diff "^26.1.0" jest-get-type "^26.0.0" - jest-matcher-utils "^26.0.1" - jest-message-util "^26.0.1" - jest-resolve "^26.0.1" - make-dir "^3.0.0" + jest-haste-map "^26.1.0" + jest-matcher-utils "^26.1.0" + jest-message-util "^26.1.0" + jest-resolve "^26.1.0" natural-compare "^1.4.0" - pretty-format "^26.0.1" + pretty-format "^26.1.0" semver "^7.3.2" -jest-util@^26.0.1: - version "26.0.1" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-26.0.1.tgz#72c4c51177b695fdd795ca072a6f94e3d7cef00a" - integrity sha512-byQ3n7ad1BO/WyFkYvlWQHTsomB6GIewBh8tlGtusiylAlaxQ1UpS0XYH0ngOyhZuHVLN79Qvl6/pMiDMSSG1g== +jest-util@^26.1.0: + version "26.1.0" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-26.1.0.tgz#80e85d4ba820decacf41a691c2042d5276e5d8d8" + integrity sha512-rNMOwFQevljfNGvbzNQAxdmXQ+NawW/J72dmddsK0E8vgxXCMtwQ/EH0BiWEIxh0hhMcTsxwAxINt7Lh46Uzbg== dependencies: - "@jest/types" "^26.0.1" + "@jest/types" "^26.1.0" chalk "^4.0.0" graceful-fs "^4.2.4" is-ci "^2.0.0" - make-dir "^3.0.0" + micromatch "^4.0.2" -jest-validate@^26.0.1: - version "26.0.1" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-26.0.1.tgz#a62987e1da5b7f724130f904725e22f4e5b2e23c" - integrity sha512-u0xRc+rbmov/VqXnX3DlkxD74rHI/CfS5xaV2VpeaVySjbb1JioNVOyly5b56q2l9ZKe7bVG5qWmjfctkQb0bA== +jest-validate@^26.1.0: + version "26.1.0" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-26.1.0.tgz#942c85ad3d60f78250c488a7f85d8f11a29788e7" + integrity sha512-WPApOOnXsiwhZtmkDsxnpye+XLb/tUISP+H6cHjfUIXvlG+eKwP+isnivsxlHCPaO9Q5wvbhloIBkdF3qUn+Nw== dependencies: - "@jest/types" "^26.0.1" + "@jest/types" "^26.1.0" camelcase "^6.0.0" chalk "^4.0.0" jest-get-type "^26.0.0" leven "^3.1.0" - pretty-format "^26.0.1" + pretty-format "^26.1.0" -jest-watcher@^26.0.1: - version "26.0.1" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-26.0.1.tgz#5b5e3ebbdf10c240e22a98af66d645631afda770" - integrity sha512-pdZPydsS8475f89kGswaNsN3rhP6lnC3/QDCppP7bg1L9JQz7oU9Mb/5xPETk1RHDCWeqmVC47M4K5RR7ejxFw== +jest-watcher@^26.1.0: + version "26.1.0" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-26.1.0.tgz#99812a0cd931f0cb3d153180426135ab83e4d8f2" + integrity sha512-ffEOhJl2EvAIki613oPsSG11usqnGUzIiK7MMX6hE4422aXOcVEG3ySCTDFLn1+LZNXGPE8tuJxhp8OBJ1pgzQ== dependencies: - "@jest/test-result" "^26.0.1" - "@jest/types" "^26.0.1" + "@jest/test-result" "^26.1.0" + "@jest/types" "^26.1.0" ansi-escapes "^4.2.1" chalk "^4.0.0" - jest-util "^26.0.1" + jest-util "^26.1.0" string-length "^4.0.1" -jest-worker@^26.0.0: - version "26.0.0" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.0.0.tgz#4920c7714f0a96c6412464718d0c58a3df3fb066" - integrity sha512-pPaYa2+JnwmiZjK9x7p9BoZht+47ecFCDFA/CJxspHzeDvQcfVBLWzCiWyo+EGrSiQMWZtCFo9iSvMZnAAo8vw== +jest-worker@^26.1.0: + version "26.1.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.1.0.tgz#65d5641af74e08ccd561c240e7db61284f82f33d" + integrity sha512-Z9P5pZ6UC+kakMbNJn+tA2RdVdNX5WH1x+5UCBZ9MxIK24pjYtFt96fK+UwBTrjLYm232g1xz0L3eTh51OW+yQ== dependencies: merge-stream "^2.0.0" supports-color "^7.0.0" -jest@^26.0.1: - version "26.0.1" - resolved "https://registry.yarnpkg.com/jest/-/jest-26.0.1.tgz#5c51a2e58dff7525b65f169721767173bf832694" - integrity sha512-29Q54kn5Bm7ZGKIuH2JRmnKl85YRigp0o0asTc6Sb6l2ch1DCXIeZTLLFy9ultJvhkTqbswF5DEx4+RlkmCxWg== +jest@^26.1.0: + version "26.1.0" + resolved "https://registry.yarnpkg.com/jest/-/jest-26.1.0.tgz#2f3aa7bcffb9bfd025473f83bbbf46a3af026263" + integrity sha512-LIti8jppw5BcQvmNJe4w2g1N/3V68HUfAv9zDVm7v+VAtQulGhH0LnmmiVkbNE4M4I43Bj2fXPiBGKt26k9tHw== dependencies: - "@jest/core" "^26.0.1" + "@jest/core" "^26.1.0" import-local "^3.0.2" - jest-cli "^26.0.1" + jest-cli "^26.1.0" js-levenshtein@^1.1.3, js-levenshtein@^1.1.6: version "1.1.6" @@ -7281,7 +7318,7 @@ jsprim@^1.2.2: json-schema "0.2.3" verror "1.10.0" -jsx-ast-utils@^2.2.3: +jsx-ast-utils@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.4.1.tgz#1114a4c1209481db06c690c2b4f488cc665f657e" integrity sha512-z1xSldJ6imESSzOjd3NNkieVJKRlKYSOtMG8SFyCj2FIrvSaSuli/WjpBkEzCBoR9bYYYFgqJw61Xhu7Lcgk+w== @@ -7874,7 +7911,7 @@ object.assign@^4.1.0: has-symbols "^1.0.0" object-keys "^1.0.11" -object.entries@^1.1.1: +object.entries@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.2.tgz#bc73f00acb6b6bb16c203434b10f9a7e797d3add" integrity sha512-BQdB9qKmb/HyNdMNWVr7O3+z5MUIx3aiegEIJqjMBbBf0YT9RRxTJSim4mzFqtyr7PDAHigq0N9dO0m0tRakQA== @@ -8642,6 +8679,13 @@ prelude-ls@~1.1.2: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= +prettier-linter-helpers@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" + integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== + dependencies: + fast-diff "^1.1.2" + prettier@1.19.1: version "1.19.1" resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb" @@ -8657,12 +8701,12 @@ pretty-format@^25.2.1, pretty-format@^25.5.0: ansi-styles "^4.0.0" react-is "^16.12.0" -pretty-format@^26.0.1: - version "26.0.1" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.0.1.tgz#a4fe54fe428ad2fd3413ca6bbd1ec8c2e277e197" - integrity sha512-SWxz6MbupT3ZSlL0Po4WF/KujhQaVehijR2blyRDCzk9e45EaYMVhMBn49fnRuHxtkSpXTes1GxNpVmH86Bxfw== +pretty-format@^26.1.0: + version "26.1.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.1.0.tgz#272b9cd1f1a924ab5d443dc224899d7a65cb96ec" + integrity sha512-GmeO1PEYdM+non4BKCj+XsPJjFOJIPnsLewqhDVoqY1xo0yNmDas7tC2XwpMrRAHR3MaE2hPo37deX5OisJ2Wg== dependencies: - "@jest/types" "^26.0.1" + "@jest/types" "^26.1.0" ansi-regex "^5.0.0" ansi-styles "^4.0.0" react-is "^16.12.0" @@ -9156,7 +9200,7 @@ resolve-url@^0.2.1: resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= -resolve@^1.10.0, resolve@^1.15.1, resolve@^1.17.0, resolve@^1.8.1: +resolve@^1.10.0, resolve@^1.17.0, resolve@^1.8.1: version "1.17.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== @@ -10480,13 +10524,6 @@ xmlchars@^2.1.1, xmlchars@^2.2.0: resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== -xregexp@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-4.3.0.tgz#7e92e73d9174a99a59743f67a4ce879a04b5ae50" - integrity sha512-7jXDIFXh5yJ/orPn4SXjuVrWWoi4Cr8jfV1eHv9CixKSbU+jY4mxfrBwAuDvupPNKpMUY+FeIqsVw/JLT9+B8g== - dependencies: - "@babel/runtime-corejs3" "^7.8.3" - xtend@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" From 1d5991e340d48910861dcde82b45983a3c852b3e Mon Sep 17 00:00:00 2001 From: Kartik Choudhary Date: Mon, 13 Jul 2020 11:30:59 +0000 Subject: [PATCH 044/116] Add Import page and Import button (#64) --- .parcelrc | 3 +- src/App.js | 1 - src/ImportPage.css | 185 ++++++++++++++++++++++++++++++++++++++ src/ImportPage.js | 100 +++++++++++++++++---- src/reactlogo.svg | 7 ++ src/util/readInputData.js | 24 +++++ 6 files changed, 300 insertions(+), 20 deletions(-) create mode 100644 src/ImportPage.css create mode 100644 src/reactlogo.svg create mode 100644 src/util/readInputData.js diff --git a/.parcelrc b/.parcelrc index 21ccbbc1af44b..3632b45b34fa7 100644 --- a/.parcelrc +++ b/.parcelrc @@ -3,6 +3,7 @@ "transformers": { "*.{json,json5}": [ "@parcel/transformer-raw" - ] + ], + "*.svg": ["@parcel/transformer-raw"] } } diff --git a/src/App.js b/src/App.js index 4fd0e60b67af5..a8a9952395e58 100644 --- a/src/App.js +++ b/src/App.js @@ -38,7 +38,6 @@ export default function App() { }); }, ); - if (profilerData && flamechart) { return ( { + // Filter null entries and sort by timestamp. + // I would not expect to have to do either of this, + // but some of the data being passed in requires it. + events = events.filter(Boolean).sort((a, b) => (a.ts > b.ts ? 1 : -1)); + + if (events.length > 0) { + const processedData = preprocessData(events); + const processedFlamechart = preprocessFlamechart(events); + onDataImported(processedData, processedFlamechart); + } + }, + [onDataImported], + ); + + // DEV only: auto-import a demo profile on component mount (i.e. page load) useEffect(() => { + if (process.env.NODE_ENV === 'production') return; fetch(JSON_PATH) .then(res => res.json()) - .then((events: TimelineEvent[]) => { - // Filter null entries and sort by timestamp. - // I would not expect to have to do either of this, - // but some of the data being passed in requires it. - events = events.filter(Boolean).sort((a, b) => (a.ts > b.ts ? 1 : -1)); - - if (events.length > 0) { - const processedData = preprocessData(events); - const processedFlamechart = preprocessFlamechart(events); - onDataImported(processedData, processedFlamechart); - } - }); - }, []); + .then(processTimeline); + }, [processTimeline]); + + const handleProfilerInput = useCallback( + async (event: File) => { + const readFile = await readInputData(event.target.files[0]); + processTimeline(JSON.parse(readFile)); + }, + [processTimeline], + ); + + const upload = useRef(null); return ( -
- LOADING. TODO: Turn this into an import page. This page currently just - immediately loads a JSON file. + ); } diff --git a/src/reactlogo.svg b/src/reactlogo.svg new file mode 100644 index 0000000000000..6b60c1042f58d --- /dev/null +++ b/src/reactlogo.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/util/readInputData.js b/src/util/readInputData.js new file mode 100644 index 0000000000000..9392492d31d24 --- /dev/null +++ b/src/util/readInputData.js @@ -0,0 +1,24 @@ +// @flow + +export const readInputData = (file: File) => { + if (!file.name.endsWith('.json')) { + console.error( + 'Invalid file type, insert a captured performance profile JSON', + ); + return; + } + // Initialize file reader + const fileReader = new FileReader(); + + return new Promise((resolve, reject) => { + fileReader.onerror = () => { + fileReader.abort(); + reject(new DOMException('Problem parsing input file.')); + }; + + fileReader.onload = () => { + resolve(fileReader.result); + }; + fileReader.readAsText(file); + }); +}; From 81ed6d5f0a10e083d0a4ba1336c33f48364eef25 Mon Sep 17 00:00:00 2001 From: Kartik Choudhary Date: Mon, 13 Jul 2020 12:06:38 +0000 Subject: [PATCH 045/116] Update preprocessData, add latest performance profile (#63) Co-authored-by: E-Liang Tan --- src/ImportPage.js | 2 +- .../__snapshots__/preprocessData-test.js.snap | 1 - src/util/__tests__/preprocessData-test.js | 92 +++++++++---------- src/util/preprocessData.js | 19 ++-- 4 files changed, 55 insertions(+), 59 deletions(-) diff --git a/src/ImportPage.js b/src/ImportPage.js index d8b274f8fdcf6..d6367da7b27d5 100644 --- a/src/ImportPage.js +++ b/src/ImportPage.js @@ -12,7 +12,7 @@ import preprocessFlamechart from './util/preprocessFlamechart'; import {readInputData} from './util/readInputData'; // TODO: Use for dev only, switch to import file after -import JSON_PATH from 'url:../static/Profile-20200625T133129.json'; +import JSON_PATH from 'url:../static/perfprofilev2.json'; type Props = {| onDataImported: ( diff --git a/src/util/__tests__/__snapshots__/preprocessData-test.js.snap b/src/util/__tests__/__snapshots__/preprocessData-test.js.snap index b3e12ceec7c9a..411d547729275 100644 --- a/src/util/__tests__/__snapshots__/preprocessData-test.js.snap +++ b/src/util/__tests__/__snapshots__/preprocessData-test.js.snap @@ -5,7 +5,6 @@ Object { "duration": 2586.895, "events": Array [ Object { - "componentName": "Unknown", "componentStack": "", "lanes": Array [ 9, diff --git a/src/util/__tests__/preprocessData-test.js b/src/util/__tests__/preprocessData-test.js index 4ee5e78dfffc1..aee183c1b791c 100644 --- a/src/util/__tests__/preprocessData-test.js +++ b/src/util/__tests__/preprocessData-test.js @@ -63,7 +63,7 @@ describe(preprocessData, () => { expect( // prettier-ignore preprocessData([ - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--schedule-render-Unknown-512-","ph":"R","pid":9312,"tid":10252,"ts":8994056569,"tts":1816966}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--schedule-render-512-","ph":"R","pid":9312,"tid":10252,"ts":8994056569,"tts":1816966}, ]), ).toEqual({ startTime: 0, @@ -139,7 +139,7 @@ describe(preprocessData, () => { {"args":{"frame":"FD65D9AFD04B1295CEA36B883F0FA82F"},"cat":"blink.user_timing,rail","name":"domLoading","ph":"R","pid":9312,"tid":10252,"ts":8993820215,"tts":1647488}, {"args":{},"cat":"blink.user_timing","name":"requestStart","ph":"R","pid":9312,"tid":10252,"ts":8993886145,"tts":1771277}, {"args":{},"cat":"blink.user_timing","name":"requestStart","ph":"R","pid":9312,"tid":10252,"ts":8993886881,"tts":1778953}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--schedule-render-Unknown-512-","ph":"R","pid":9312,"tid":10252,"ts":8994056569,"tts":1816966}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--schedule-render-512-","ph":"R","pid":9312,"tid":10252,"ts":8994056569,"tts":1816966}, {"args":{"frame":"FD65D9AFD04B1295CEA36B883F0FA82F"},"cat":"blink.user_timing,rail","name":"domInteractive","ph":"R","pid":9312,"tid":10252,"ts":8994058638,"tts":1818851}, {"args":{"frame":"FD65D9AFD04B1295CEA36B883F0FA82F"},"cat":"blink.user_timing,rail","name":"domContentLoadedEventStart","ph":"R","pid":9312,"tid":10252,"ts":8994058898,"tts":1819078}, {"args":{"frame":"FD65D9AFD04B1295CEA36B883F0FA82F"},"cat":"blink.user_timing,rail","name":"domContentLoadedEventEnd","ph":"R","pid":9312,"tid":10252,"ts":8994060045,"tts":1820100}, @@ -224,27 +224,27 @@ describe(preprocessData, () => { {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994421702,"tts":2103047}, {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994429611,"tts":2110142}, {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994429835,"tts":2110349}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-ResourceButton-0-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994436841,"tts":2115594}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-0-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994436841,"tts":2115594}, {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994437451,"tts":2116087}, {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994437941,"tts":2116287}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-ResourceButton-1-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994439235,"tts":2117153}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-ResourceButton-2-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994441050,"tts":2118088}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-ResourceButton-3-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994441951,"tts":2118783}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-ResourceButton-4-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994442698,"tts":2119371}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-1-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994439235,"tts":2117153}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-2-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994441050,"tts":2118088}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-3-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994441951,"tts":2118783}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-4-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994442698,"tts":2119371}, {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994443276,"tts":2119875}, {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994443448,"tts":2120040}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-ResourceButton-0-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994445176,"tts":2121499}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-ResourceButton-1-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994445697,"tts":2121968}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-ResourceButton-2-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994446236,"tts":2122460}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-ResourceButton-3-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994446778,"tts":2122951}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-ResourceButton-4-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994447344,"tts":2123444}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-0-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994445176,"tts":2121499}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-1-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994445697,"tts":2121968}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-2-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994446236,"tts":2122460}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-3-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994446778,"tts":2122951}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-4-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994447344,"tts":2123444}, {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994449037,"tts":2124925}, {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994449280,"tts":2125142}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-ResourceButton-0-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at SuspenseList\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994449831,"tts":2125639}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-0-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at SuspenseList\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994449831,"tts":2125639}, {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-stop","ph":"R","pid":9312,"tid":10252,"ts":8994450864,"tts":2126555}, {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--commit-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994451820,"tts":2127417}, {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--layout-effects-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994455732,"tts":2130777}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--schedule-state-update-ForceUpdateDemo_ForceUpdateDemo-1-\n at ForceUpdateDemo_ForceUpdateDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:18:98)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994457934,"tts":2132671}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--schedule-state-update-1-ForceUpdateDemo_ForceUpdateDemo-\n at ForceUpdateDemo_ForceUpdateDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:18:98)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994457934,"tts":2132671}, {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--layout-effects-stop","ph":"R","pid":9312,"tid":10252,"ts":8994458421,"tts":2133089}, {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-1","ph":"R","pid":9312,"tid":10252,"ts":8994462600,"tts":2136847}, {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-stop","ph":"R","pid":9312,"tid":10252,"ts":8994464817,"tts":2138817}, @@ -253,61 +253,61 @@ describe(preprocessData, () => { {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--layout-effects-stop","ph":"R","pid":9312,"tid":10252,"ts":8994465784,"tts":2139686}, {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--commit-stop","ph":"R","pid":9312,"tid":10252,"ts":8994466156,"tts":2140023}, {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--commit-stop","ph":"R","pid":9312,"tid":10252,"ts":8994466372,"tts":2140208}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-ResourceButton-1-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995573418,"tts":2205582}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-ResourceButton-1-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995573870,"tts":2205980}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-1-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995573418,"tts":2205582}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-1-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995573870,"tts":2205980}, {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-1024","ph":"R","pid":9312,"tid":10252,"ts":8995574538,"tts":2206568}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-ResourceButton-0-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995575662,"tts":2207534}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-ResourceButton-2-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995576307,"tts":2208142}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-ResourceButton-3-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995576659,"tts":2208445}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-ResourceButton-4-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995577001,"tts":2208736}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-0-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995575662,"tts":2207534}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-2-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995576307,"tts":2208142}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-3-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995576659,"tts":2208445}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-4-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995577001,"tts":2208736}, {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-stop","ph":"R","pid":9312,"tid":10252,"ts":8995577971,"tts":2209602}, {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--commit-start-1024","ph":"R","pid":9312,"tid":10252,"ts":8995578068,"tts":2209689}, {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--layout-effects-start-1024","ph":"R","pid":9312,"tid":10252,"ts":8995580101,"tts":2211495}, {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--layout-effects-stop","ph":"R","pid":9312,"tid":10252,"ts":8995580122,"tts":2211515}, {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--commit-stop","ph":"R","pid":9312,"tid":10252,"ts":8995580657,"tts":2211995}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-ResourceButton-2-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995644745,"tts":2217336}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-ResourceButton-2-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995645038,"tts":2217571}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-ResourceButton-2-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995645354,"tts":2217861}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-2-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995644745,"tts":2217336}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-2-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995645038,"tts":2217571}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-2-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995645354,"tts":2217861}, {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-2048","ph":"R","pid":9312,"tid":10252,"ts":8995645494,"tts":2217999}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-ResourceButton-0-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995646312,"tts":2218721}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-ResourceButton-3-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995647134,"tts":2219450}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-ResourceButton-4-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995647462,"tts":2219740}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-0-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995646312,"tts":2218721}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-3-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995647134,"tts":2219450}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-4-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995647462,"tts":2219740}, {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-stop","ph":"R","pid":9312,"tid":10252,"ts":8995648162,"tts":2220335}, {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--commit-start-2048","ph":"R","pid":9312,"tid":10252,"ts":8995648191,"tts":2220363}, {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--layout-effects-start-2048","ph":"R","pid":9312,"tid":10252,"ts":8995649260,"tts":2221320}, {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--layout-effects-stop","ph":"R","pid":9312,"tid":10252,"ts":8995649280,"tts":2221340}, {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--commit-stop","ph":"R","pid":9312,"tid":10252,"ts":8995649611,"tts":2221636}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-ResourceButton-3-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995758769,"tts":2228839}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-ResourceButton-3-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995759018,"tts":2229064}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-ResourceButton-3-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995759442,"tts":2229424}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-ResourceButton-3-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995759660,"tts":2229627}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-3-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995758769,"tts":2228839}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-3-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995759018,"tts":2229064}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-3-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995759442,"tts":2229424}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-3-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995759660,"tts":2229627}, {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-4096","ph":"R","pid":9312,"tid":10252,"ts":8995759857,"tts":2229803}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-ResourceButton-0-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995760575,"tts":2230456}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-ResourceButton-4-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995761666,"tts":2231399}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-0-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995760575,"tts":2230456}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-4-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995761666,"tts":2231399}, {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-stop","ph":"R","pid":9312,"tid":10252,"ts":8995762296,"tts":2231965}, {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--commit-start-4096","ph":"R","pid":9312,"tid":10252,"ts":8995762367,"tts":2232017}, {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--layout-effects-start-4096","ph":"R","pid":9312,"tid":10252,"ts":8995763427,"tts":2232966}, {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--layout-effects-stop","ph":"R","pid":9312,"tid":10252,"ts":8995763454,"tts":2232993}, {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--commit-stop","ph":"R","pid":9312,"tid":10252,"ts":8995763625,"tts":2233154}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-ResourceButton-4-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996158083,"tts":2252466}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-ResourceButton-4-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996158391,"tts":2252730}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-ResourceButton-4-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996158738,"tts":2253038}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-ResourceButton-4-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996158983,"tts":2253239}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-ResourceButton-4-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996159231,"tts":2253447}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-4-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996158083,"tts":2252466}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-4-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996158391,"tts":2252730}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-4-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996158738,"tts":2253038}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-4-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996158983,"tts":2253239}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-4-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996159231,"tts":2253447}, {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-8192","ph":"R","pid":9312,"tid":10252,"ts":8996159465,"tts":2253624}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-ResourceButton-0-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996160268,"tts":2254312}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-0-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996160268,"tts":2254312}, {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-stop","ph":"R","pid":9312,"tid":10252,"ts":8996161775,"tts":2255670}, {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--commit-start-8192","ph":"R","pid":9312,"tid":10252,"ts":8996161834,"tts":2255716}, {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--layout-effects-start-8192","ph":"R","pid":9312,"tid":10252,"ts":8996163031,"tts":2256754}, {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--layout-effects-stop","ph":"R","pid":9312,"tid":10252,"ts":8996163051,"tts":2256773}, {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--commit-stop","ph":"R","pid":9312,"tid":10252,"ts":8996163355,"tts":2257045}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-ResourceButton-0-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996357682,"tts":2267920}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-ResourceButton-0-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996357983,"tts":2268179}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-ResourceButton-0-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at SuspenseList\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996358231,"tts":2268389}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-ResourceButton-0-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996358538,"tts":2268679}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-ResourceButton-0-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996358786,"tts":2268867}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-ResourceButton-0-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996359042,"tts":2269066}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-ResourceButton-0-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996359296,"tts":2269264}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-0-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996357682,"tts":2267920}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-0-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996357983,"tts":2268179}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-0-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at SuspenseList\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996358231,"tts":2268389}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-0-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996358538,"tts":2268679}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-0-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996358786,"tts":2268867}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-0-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996359042,"tts":2269066}, + {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-0-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996359296,"tts":2269264}, {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-16384","ph":"R","pid":9312,"tid":10252,"ts":8996359448,"tts":2269412}, {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-stop","ph":"R","pid":9312,"tid":10252,"ts":8996362873,"tts":2272363}, {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--commit-start-16384","ph":"R","pid":9312,"tid":10252,"ts":8996362944,"tts":2272420}, @@ -323,7 +323,7 @@ describe(preprocessData, () => { // prettier-ignore preprocessData([ {"args":{"data":{"startTime":40806924876}},"cat":"disabled-by-default-v8.cpu_profiler","id":"0x2","name":"Profile","ph":"P","pid":1852,"tid":12484,"ts":40806924880,"tts":996658}, - {"args":{"data":{"navigationId":"1065756F5FDAD64BE45CA86B0BBC1F8B"}},"cat":"blink.user_timing","name":"--schedule-forced-update-ForceUpdateDemo_ForceUpdateDemo-16-\n at ForceUpdateDemo_ForceUpdateDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:18:98)\n at App","ph":"R","pid":1852,"tid":12484,"ts":40806988231,"tts":1037762}, + {"args":{"data":{"navigationId":"1065756F5FDAD64BE45CA86B0BBC1F8B"}},"cat":"blink.user_timing","name":"--schedule-forced-update-16-ForceUpdateDemo_ForceUpdateDemo-\n at ForceUpdateDemo_ForceUpdateDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:18:98)\n at App","ph":"R","pid":1852,"tid":12484,"ts":40806988231,"tts":1037762}, {"args":{"data":{"navigationId":"1065756F5FDAD64BE45CA86B0BBC1F8B"}},"cat":"blink.user_timing","name":"--render-start-16","ph":"R","pid":1852,"tid":12484,"ts":40806990146,"tts":1038890}, {"args":{"data":{"navigationId":"1065756F5FDAD64BE45CA86B0BBC1F8B"}},"cat":"blink.user_timing","name":"--render-stop","ph":"R","pid":1852,"tid":12484,"ts":40806991123,"tts":1039401}, {"args":{"data":{"navigationId":"1065756F5FDAD64BE45CA86B0BBC1F8B"}},"cat":"blink.user_timing","name":"--commit-start-16","ph":"R","pid":1852,"tid":12484,"ts":40806991170,"tts":1039447}, diff --git a/src/util/preprocessData.js b/src/util/preprocessData.js index 4a3bc8aff7aea..0c28c1db8980d 100644 --- a/src/util/preprocessData.js +++ b/src/util/preprocessData.js @@ -150,22 +150,19 @@ function processTimelineEvent( // React Events - schedule if (name.startsWith('--schedule-render-')) { - const [ - componentName, - laneBitmaskString, - ...splitComponentStack - ] = name.substr(18).split('-'); + const [laneBitmaskString, ...splitComponentStack] = name + .substr(18) + .split('-'); currentProfilerData.events.push({ type: 'schedule-render', lanes: getLanesFromTransportDecimalBitmask(laneBitmaskString), - componentName, componentStack: splitComponentStack.join('-'), timestamp: startTime, }); } else if (name.startsWith('--schedule-forced-update-')) { const [ - componentName, laneBitmaskString, + componentName, ...splitComponentStack ] = name.substr(25).split('-'); const isCascading = !!state.measureStack.find( @@ -181,8 +178,8 @@ function processTimelineEvent( }); } else if (name.startsWith('--schedule-state-update-')) { const [ - componentName, laneBitmaskString, + componentName, ...splitComponentStack ] = name.substr(24).split('-'); const isCascading = !!state.measureStack.find( @@ -200,7 +197,7 @@ function processTimelineEvent( // React Events - suspense else if (name.startsWith('--suspense-suspend-')) { - const [componentName, id, ...splitComponentStack] = name + const [id, componentName, ...splitComponentStack] = name .substr(19) .split('-'); currentProfilerData.events.push({ @@ -211,7 +208,7 @@ function processTimelineEvent( timestamp: startTime, }); } else if (name.startsWith('--suspense-resolved-')) { - const [componentName, id, ...splitComponentStack] = name + const [id, componentName, ...splitComponentStack] = name .substr(20) .split('-'); currentProfilerData.events.push({ @@ -222,7 +219,7 @@ function processTimelineEvent( timestamp: startTime, }); } else if (name.startsWith('--suspense-rejected-')) { - const [componentName, id, ...splitComponentStack] = name + const [id, componentName, ...splitComponentStack] = name .substr(20) .split('-'); currentProfilerData.events.push({ From 3f78fdcaf9cc91f8cf793598f09a8b114c059df5 Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Wed, 15 Jul 2020 18:38:45 +0800 Subject: [PATCH 046/116] Add basic README (#66) --- README.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000000000..bea72495ced6f --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +# Experimental React Concurrent Mode Profiler + +- Deployed at: https://react-scheduling-profiler.vercel.app +- Context: https://github.com/MLH-Fellowship/0.4.x-projects/wiki/React-Concurrent-Mode-Profiler \ No newline at end of file From 02acac0f347a55f986ac37ccb4db4622ae774b9f Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Tue, 21 Jul 2020 13:18:32 +0800 Subject: [PATCH 047/116] Fix Flow large memory usage (#79) --- .flowconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.flowconfig b/.flowconfig index 3e03152eed269..cb5d0a9142649 100644 --- a/.flowconfig +++ b/.flowconfig @@ -11,5 +11,8 @@ [lints] [options] +module.file_ext=.js +module.file_ext=.mjs +module.file_ext=.cjs [strict] From 8d98ae002edacd8f287bf28881a851a25d1704de Mon Sep 17 00:00:00 2001 From: Kartik Choudhary Date: Mon, 27 Jul 2020 07:08:25 +0000 Subject: [PATCH 048/116] Remove link to a private internal repo (#81) --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index bea72495ced6f..b3e0b07b05b2a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,3 @@ # Experimental React Concurrent Mode Profiler - Deployed at: https://react-scheduling-profiler.vercel.app -- Context: https://github.com/MLH-Fellowship/0.4.x-projects/wiki/React-Concurrent-Mode-Profiler \ No newline at end of file From 474a424d0b4726c6a4083269001d53f7d0454b7b Mon Sep 17 00:00:00 2001 From: Kartik Choudhary Date: Mon, 27 Jul 2020 07:09:47 +0000 Subject: [PATCH 049/116] Fix tooltip bug, truncate componentName to use ellipsis (#78) * Fix tooltip bug, truncate componentName to use ellipsis * Fix canvas reset bug * remove ellipsis CSS, truncated componentName and script URL * remove unused css, fix URL overflow, set ellipsis to 128, remove ellipsis for URL --- src/CanvasPage.css | 1 + src/EventTooltip.css | 6 +++--- src/EventTooltip.js | 13 ++++++++++--- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/CanvasPage.css b/src/CanvasPage.css index e5d238a0d9d2c..0a22311f084dd 100644 --- a/src/CanvasPage.css +++ b/src/CanvasPage.css @@ -4,4 +4,5 @@ bottom: 0.5rem; left: 0.5rem; right: 0.5rem; + overflow: hidden; } diff --git a/src/EventTooltip.css b/src/EventTooltip.css index 4cb2acc4aa2a5..2403d6d73d388 100644 --- a/src/EventTooltip.css +++ b/src/EventTooltip.css @@ -23,20 +23,20 @@ padding-top: 5px; grid-gap: 2px 5px; grid-template-columns: min-content auto; - word-break: break-word; } .DetailsGridLabel { color: #666; text-align: right; - white-space: nowrap; } -.Duration { +.DetailsGridURL{ + overflow: hidden; } .ComponentName { font-weight: bold; + word-wrap: break-word; } .ComponentStack { diff --git a/src/EventTooltip.js b/src/EventTooltip.js index 3994a9fdbbf99..9b0a0e6cb5865 100644 --- a/src/EventTooltip.js +++ b/src/EventTooltip.js @@ -31,6 +31,13 @@ function formatDuration(ms) { return prettyMilliseconds(ms, {millisecondsDecimalDigits: 3}); } +function trimComponentName(name) { + if (name.length > 128) { + return name.substring(0, 127) + '...'; + } + return name; +} + export default function EventTooltip({data, hoveredEvent, state}: Props) { const {canvasMouseY, canvasMouseX} = state; @@ -140,14 +147,14 @@ const TooltipFlamechartNode = ({ color: COLORS.TOOLTIP, }} ref={tooltipRef}> - {formatDuration((end - start) / 1000)} {name} + {formatDuration((end - start) / 1000)} {trimComponentName(name)}
Timestamp:
{formatTimestamp(start / 1000)}
{file && ( <>
Script URL:
-
{file}
+
{file}
)} {(line !== undefined || col !== undefined) && ( @@ -208,7 +215,7 @@ const TooltipReactEvent = ({ ref={tooltipRef}> {componentName && ( - {componentName} + {trimComponentName(componentName)} )}{' '} {label} From 19b1fcf3b550d0e42309431d6fb14e4c8565d4df Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Tue, 28 Jul 2020 12:13:41 +0800 Subject: [PATCH 050/116] Reimplement canvas using view classes (#80) Replaces Brian's original procedural code with view classes. The views are rudimentary implementations of iOS UIKit-style UIViews. --- src/App.js | 23 +- src/CanvasPage.js | 290 +++++++++--- src/EventTooltip.js | 12 +- src/canvas/canvasUtils.js | 66 ++- src/canvas/constants.js | 1 - src/canvas/getHoveredEvent.js | 241 ---------- src/canvas/renderCanvas.js | 563 ------------------------ src/canvas/views/FlamegraphView.js | 246 +++++++++++ src/canvas/views/ReactEventsView.js | 246 +++++++++++ src/canvas/views/ReactMeasuresView.js | 304 +++++++++++++ src/canvas/views/TimeAxisMarkersView.js | 160 +++++++ src/canvas/views/index.js | 6 + src/layout/HorizontalPanAndZoomView.js | 299 +++++++++++++ src/layout/StaticLayoutView.js | 90 ++++ src/layout/Surface.js | 51 +++ src/layout/VerticalScrollView.js | 196 +++++++++ src/layout/View.js | 113 +++++ src/layout/geometry.js | 88 ++++ src/layout/index.js | 8 + src/types.js | 1 - src/useCanvasInteraction.js | 234 ++++++++++ src/util/useInteractiveEvents.js | 132 ------ src/util/usePanAndZoom.js | 403 ----------------- 23 files changed, 2312 insertions(+), 1461 deletions(-) delete mode 100644 src/canvas/getHoveredEvent.js delete mode 100644 src/canvas/renderCanvas.js create mode 100644 src/canvas/views/FlamegraphView.js create mode 100644 src/canvas/views/ReactEventsView.js create mode 100644 src/canvas/views/ReactMeasuresView.js create mode 100644 src/canvas/views/TimeAxisMarkersView.js create mode 100644 src/canvas/views/index.js create mode 100644 src/layout/HorizontalPanAndZoomView.js create mode 100644 src/layout/StaticLayoutView.js create mode 100644 src/layout/Surface.js create mode 100644 src/layout/VerticalScrollView.js create mode 100644 src/layout/View.js create mode 100644 src/layout/geometry.js create mode 100644 src/layout/index.js create mode 100644 src/useCanvasInteraction.js delete mode 100644 src/util/useInteractiveEvents.js delete mode 100644 src/util/usePanAndZoom.js diff --git a/src/App.js b/src/App.js index a8a9952395e58..00c91728b5a95 100644 --- a/src/App.js +++ b/src/App.js @@ -1,12 +1,10 @@ // @flow -import type {FlamechartData, ReactLane, ReactProfilerData} from './types'; +import type {FlamechartData, ReactProfilerData} from './types'; import React, {useState, useCallback} from 'react'; import {unstable_batchedUpdates} from 'react-dom'; -import {getLaneHeight} from './canvas/canvasUtils'; -import {REACT_TOTAL_NUM_LANES} from './constants'; import ImportPage from './ImportPage'; import CanvasPage from './CanvasPage'; @@ -15,7 +13,6 @@ export default function App() { null, ); const [flamechart, setFlamechart] = useState(null); - const [schedulerCanvasHeight, setSchedulerCanvasHeight] = useState(0); const handleDataImported = useCallback( ( @@ -25,27 +22,11 @@ export default function App() { unstable_batchedUpdates(() => { setProfilerData(importedProfilerData); setFlamechart(importedFlamechart); - - const lanesToRender: ReactLane[] = Array.from( - Array(REACT_TOTAL_NUM_LANES).keys(), - ); - // TODO: Figure out if this is necessary - setSchedulerCanvasHeight( - lanesToRender.reduce((height, lane) => { - return height + getLaneHeight(importedProfilerData, lane); - }, 0), - ); }); }, ); if (profilerData && flamechart) { - return ( - - ); + return ; } else { return ; } diff --git a/src/CanvasPage.js b/src/CanvasPage.js index 74eaf1fb0fc24..c89719f70398f 100644 --- a/src/CanvasPage.js +++ b/src/CanvasPage.js @@ -1,25 +1,33 @@ // @flow -import type {PanAndZoomState} from './util/usePanAndZoom'; +import type {Point} from './layout'; import {copy} from 'clipboard-js'; -import React, {Fragment, useLayoutEffect, useRef, useState} from 'react'; -import usePanAndZoom from './util/usePanAndZoom'; +import React, { + Fragment, + useEffect, + useLayoutEffect, + useRef, + useState, + useCallback, +} from 'react'; -import {getHoveredEvent} from './canvas/getHoveredEvent'; -import {renderCanvas} from './canvas/renderCanvas'; +import { + HorizontalPanAndZoomView, + VerticalScrollView, + Surface, + StaticLayoutView, + layeredLayout, + zeroPoint, + verticallyStackedLayout, +} from './layout'; import prettyMilliseconds from 'pretty-ms'; import {getBatchRange} from './util/getBatchRange'; import EventTooltip from './EventTooltip'; import styles from './CanvasPage.css'; import AutoSizer from 'react-virtualized-auto-sizer'; -import { - COLORS, - FLAMECHART_FRAME_HEIGHT, - LABEL_FIXED_WIDTH, - HEADER_HEIGHT_FIXED, -} from './canvas/constants'; +import {COLORS} from './canvas/constants'; import {ContextMenu, ContextMenuItem, useContextMenu} from './context'; @@ -30,32 +38,36 @@ import type { ReactHoverContextInfo, ReactProfilerData, } from './types'; +import {useCanvasInteraction} from './useCanvasInteraction'; +import { + FlamegraphView, + ReactEventsView, + ReactMeasuresView, + TimeAxisMarkersView, +} from './canvas/views'; type ContextMenuContextData = {| data: ReactProfilerData, flamechart: FlamechartData, hoveredEvent: ReactHoverContextInfo | null, - state: PanAndZoomState, |}; type Props = {| profilerData: ReactProfilerData, flamechart: FlamechartData, - schedulerCanvasHeight: number, |}; -function CanvasPage({profilerData, flamechart, schedulerCanvasHeight}: Props) { +function CanvasPage({profilerData, flamechart}: Props) { return (
+ style={{backgroundColor: COLORS.BACKGROUND}}> {({height, width}: {height: number, width: number}) => ( )} @@ -79,21 +91,21 @@ const copySummary = (data, measure) => { ); }; -const zoomToBatch = (data, measure, state) => { - const {zoomTo} = state; - if (!zoomTo) { - return; - } - const {batchUID} = measure; - const [startTime, stopTime] = getBatchRange(batchUID, data); - zoomTo(startTime, stopTime); -}; +// TODO: Migrate zoomToBatch to new views architecture +// const zoomToBatch = (data, measure, state) => { +// const {zoomTo} = state; +// if (!zoomTo) { +// return; +// } +// const {batchUID} = measure; +// const [startTime, stopTime] = getBatchRange(batchUID, data); +// zoomTo(startTime, stopTime); +// }; type AutoSizedCanvasProps = {| data: ReactProfilerData, flamechart: FlamechartData, height: number, - schedulerCanvasHeight: number, width: number, |}; @@ -101,55 +113,212 @@ function AutoSizedCanvas({ data, flamechart, height, - schedulerCanvasHeight, width, }: AutoSizedCanvasProps) { const canvasRef = useRef(null); - const state = usePanAndZoom({ - canvasRef, - canvasHeight: height, - canvasWidth: width, - fixedColumnWidth: LABEL_FIXED_WIDTH, - fixedHeaderHeight: HEADER_HEIGHT_FIXED, - unscaledContentWidth: data.duration, - unscaledContentHeight: - schedulerCanvasHeight + - flamechart.layers.length * FLAMECHART_FRAME_HEIGHT, - }); + const [isContextMenuShown, setIsContextMenuShown] = useState(false); + const [mouseLocation, setMouseLocation] = useState(zeroPoint); // DOM coordinates + const [ + hoveredEvent, + setHoveredEvent, + ] = useState(null); + + const surfaceRef = useRef(new Surface()); + const flamegraphViewRef = useRef(null); + const axisMarkersViewRef = useRef(null); + const reactEventsViewRef = useRef(null); + const reactMeasuresViewRef = useRef(null); + const rootViewRef = useRef(null); + + useLayoutEffect(() => { + const axisMarkersView = new TimeAxisMarkersView( + surfaceRef.current, + {origin: zeroPoint, size: {width, height}}, + data.duration, + ); + axisMarkersViewRef.current = axisMarkersView; + + const reactEventsView = new ReactEventsView( + surfaceRef.current, + {origin: zeroPoint, size: {width, height}}, + data, + ); + reactEventsViewRef.current = reactEventsView; + + const reactMeasuresView = new ReactMeasuresView( + surfaceRef.current, + {origin: zeroPoint, size: {width, height}}, + data, + ); + reactMeasuresViewRef.current = reactMeasuresView; + + const flamegraphView = new FlamegraphView( + surfaceRef.current, + {origin: zeroPoint, size: {width, height}}, + flamechart, + data, + ); + flamegraphViewRef.current = flamegraphView; + const flamegraphVScrollWrapper = new VerticalScrollView( + surfaceRef.current, + {origin: zeroPoint, size: {width, height}}, + flamegraphView, + flamegraphView.intrinsicSize.height, + ); + + const stackedZoomables = new StaticLayoutView( + surfaceRef.current, + {origin: zeroPoint, size: {width, height}}, + verticallyStackedLayout, + [ + axisMarkersView, + reactEventsView, + reactMeasuresView, + flamegraphVScrollWrapper, + ], + ); + + const contentZoomWrapper = new HorizontalPanAndZoomView( + surfaceRef.current, + {origin: zeroPoint, size: {width, height}}, + stackedZoomables, + flamegraphView.intrinsicSize.width, + ); + + rootViewRef.current = new StaticLayoutView( + surfaceRef.current, + {origin: zeroPoint, size: {width, height}}, + layeredLayout, + [contentZoomWrapper], + ); + + surfaceRef.current.rootView = rootViewRef.current; + }, [data, flamechart, setHoveredEvent]); - const hoveredEvent = getHoveredEvent( - schedulerCanvasHeight, - data, - flamechart, - state, + useLayoutEffect(() => { + if (canvasRef.current) { + surfaceRef.current.setCanvas(canvasRef.current, {width, height}); + } + }, [surfaceRef, canvasRef, width, height]); + + const interactor = useCallback( + interaction => { + if ( + hoveredEvent && + (hoveredEvent.event || + hoveredEvent.measure || + hoveredEvent.flamechartNode) + ) { + setMouseLocation({ + x: interaction.payload.event.x, + y: interaction.payload.event.y, + }); + } + if (canvasRef.current === null) { + return; + } + surfaceRef.current.handleInteraction(interaction); + surfaceRef.current.displayIfNeeded(); + }, + [surfaceRef, hoveredEvent, setMouseLocation], ); - const [isContextMenuShown, setIsContextMenuShown] = useState(false); + + useCanvasInteraction(canvasRef, interactor); useContextMenu({ data: { data, flamechart, hoveredEvent, - state, }, id: CONTEXT_MENU_ID, onChange: setIsContextMenuShown, ref: canvasRef, }); + useEffect(() => { + const {current: reactEventsView} = reactEventsViewRef; + if (reactEventsView) { + reactEventsView.onHover = event => { + if (!hoveredEvent || hoveredEvent.event !== event) { + setHoveredEvent({ + event, + flamechartNode: null, + measure: null, + data, + }); + } + }; + } + + const {current: reactMeasuresView} = reactMeasuresViewRef; + if (reactMeasuresView) { + reactMeasuresView.onHover = measure => { + if (!hoveredEvent || hoveredEvent.measure !== measure) { + setHoveredEvent({ + event: null, + flamechartNode: null, + measure, + data, + }); + } + }; + } + + const {current: flamegraphView} = flamegraphViewRef; + if (flamegraphView) { + flamegraphView.onHover = flamechartNode => { + if (!hoveredEvent || hoveredEvent.flamechartNode !== flamechartNode) { + setHoveredEvent({ + event: null, + flamechartNode, + measure: null, + data, + }); + } + }; + } + }, [ + reactEventsViewRef, + reactMeasuresViewRef, + flamegraphViewRef, + hoveredEvent, + setHoveredEvent, + ]); + useLayoutEffect(() => { - if (canvasRef.current !== null) { - renderCanvas( - data, - flamechart, - canvasRef.current, - width, - height, - state, - hoveredEvent, + const {current: reactEventsView} = reactEventsViewRef; + if (reactEventsView) { + reactEventsView.setHoveredEvent(hoveredEvent ? hoveredEvent.event : null); + } + + const {current: reactMeasuresView} = reactMeasuresViewRef; + if (reactMeasuresView) { + reactMeasuresView.setHoveredMeasure( + hoveredEvent ? hoveredEvent.measure : null, + ); + } + + const {current: flamegraphView} = flamegraphViewRef; + if (flamegraphView) { + flamegraphView.setHoveredFlamechartNode( + hoveredEvent ? hoveredEvent.flamechartNode : null, ); } + }, [ + reactEventsViewRef, + reactMeasuresViewRef, + flamegraphViewRef, + hoveredEvent, + ]); + + // When React component renders, rerender surface. + // TODO: See if displaying on rAF would make more sense since we're somewhat + // decoupled from React and we don't want to render canvas multiple times per + // frame. + useLayoutEffect(() => { + surfaceRef.current.displayIfNeeded(); }); return ( @@ -177,13 +346,13 @@ function AutoSizedCanvas({ Copy component stack )} - {measure !== null && ( + {/* {measure !== null && ( zoomToBatch(contextData.data, measure, state)} title="Zoom to batch"> Zoom to batch - )} + )} */} {measure !== null && ( copySummary(contextData.data, measure)} @@ -202,7 +371,8 @@ function AutoSizedCanvas({ copy( - `line ${flamechartNode.node.frame.line}, column ${flamechartNode.node.frame.col}`, + `line ${flamechartNode.node.frame.line || + ''}, column ${flamechartNode.node.frame.col || ''}`, ) } title="Copy location"> @@ -214,7 +384,11 @@ function AutoSizedCanvas({ }} {!isContextMenuShown && ( - + )} ); diff --git a/src/EventTooltip.js b/src/EventTooltip.js index 9b0a0e6cb5865..3ab48ac4474db 100644 --- a/src/EventTooltip.js +++ b/src/EventTooltip.js @@ -1,6 +1,6 @@ // @flow -import type {PanAndZoomState} from './util/usePanAndZoom'; +import type {Point} from './layout'; import type {FlamechartFrame} from '@elg/speedscope'; import type { ReactEvent, @@ -20,7 +20,7 @@ import styles from './EventTooltip.css'; type Props = {| data: ReactProfilerData, hoveredEvent: ReactHoverContextInfo | null, - state: PanAndZoomState, + origin: Point, |}; function formatTimestamp(ms) { @@ -38,12 +38,10 @@ function trimComponentName(name) { return name; } -export default function EventTooltip({data, hoveredEvent, state}: Props) { - const {canvasMouseY, canvasMouseX} = state; - +export default function EventTooltip({data, hoveredEvent, origin}: Props) { const tooltipRef = useSmartTooltip({ - mouseX: canvasMouseX, - mouseY: canvasMouseY, + mouseX: origin.x, + mouseY: origin.y, }); if (hoveredEvent === null) { diff --git a/src/canvas/canvasUtils.js b/src/canvas/canvasUtils.js index ae76961bc4aaf..96508a61f423f 100644 --- a/src/canvas/canvasUtils.js +++ b/src/canvas/canvasUtils.js @@ -1,16 +1,10 @@ // @flow // Contains helper functions for rendering canvas elements -import type {ReactLane, ReactProfilerData} from '../types'; +import type {Rect} from '../layout'; import memoize from 'memoize-one'; -import { - INTERVAL_TIMES, - MAX_INTERVAL_SIZE_PX, - REACT_GUTTER_SIZE, - REACT_WORK_SIZE, - REACT_WORK_BORDER_SIZE, -} from './constants'; +import {INTERVAL_TIMES, MAX_INTERVAL_SIZE_PX} from './constants'; // hidpi canvas: https://www.html5rocks.com/en/tutorials/canvas/hidpi/ function configureRetinaCanvas(canvas, height, width) { @@ -39,20 +33,6 @@ export const getCanvasContext = memoize( }, ); -export function getCanvasMousePos( - canvas: HTMLCanvasElement, - mouseEvent: MouseEvent, -) { - const rect = - canvas instanceof HTMLCanvasElement - ? canvas.getBoundingClientRect() - : {left: 0, top: 0}; - const canvasMouseX = mouseEvent.clientX - rect.left; - const canvasMouseY = mouseEvent.clientY - rect.top; - - return {canvasMouseX, canvasMouseY}; -} - // Time mark intervals vary based on the current zoom range and the time it represents. // In Chrome, these seem to range from 70-140 pixels wide. // Time wise, they represent intervals of e.g. 1s, 500ms, 200ms, 100ms, 50ms, 20ms. @@ -92,15 +72,33 @@ export const trimFlamegraphText = ( return null; }; -export const getLaneHeight = ( - data: $ReadOnly, - lane: ReactLane, -): number => { - // TODO: Return 0 if data has no data for lane - return ( - REACT_GUTTER_SIZE + - REACT_WORK_SIZE + - REACT_GUTTER_SIZE + - REACT_WORK_BORDER_SIZE - ); -}; +export function positioningScaleFactor( + intrinsicWidth: number, + frame: Rect, +): number { + return frame.size.width / intrinsicWidth; +} + +export function timestampToPosition( + timestamp: number, + scaleFactor: number, + frame: Rect, +): number { + return frame.origin.x + timestamp * scaleFactor; +} + +export function positionToTimestamp( + position: number, + scaleFactor: number, + frame: Rect, +): number { + return (position - frame.origin.x) / scaleFactor; +} + +export function durationToWidth(duration: number, scaleFactor: number): number { + return duration * scaleFactor; +} + +export function widthToDuration(width: number, scaleFactor: number): number { + return width / scaleFactor; +} diff --git a/src/canvas/constants.js b/src/canvas/constants.js index 09b58a59f335e..7aaebf9f84428 100644 --- a/src/canvas/constants.js +++ b/src/canvas/constants.js @@ -10,7 +10,6 @@ export const MARKER_TEXT_PADDING = 8; export const BAR_HEIGHT = 16; export const BAR_HORIZONTAL_SPACING = 1; export const BAR_SPACER_SIZE = 6; -export const EVENT_SIZE = 6; // TODO: What's the difference between this and REACT_EVENT_SIZE? export const MIN_BAR_WIDTH = 1; export const SECTION_GUTTER_SIZE = 4; diff --git a/src/canvas/getHoveredEvent.js b/src/canvas/getHoveredEvent.js deleted file mode 100644 index c23d56337f59f..0000000000000 --- a/src/canvas/getHoveredEvent.js +++ /dev/null @@ -1,241 +0,0 @@ -// @flow - -import type { - FlamechartData, - ReactHoverContextInfo, - ReactLane, - ReactProfilerData, -} from '../types'; -import type {PanAndZoomState} from '../util/usePanAndZoom'; - -import { - durationToWidth, - positionToTimestamp, - timestampToPosition, -} from '../util/usePanAndZoom'; -import {REACT_TOTAL_NUM_LANES} from '../constants'; - -import {getLaneHeight} from './canvasUtils'; -import { - HEADER_HEIGHT_FIXED, - REACT_EVENT_SIZE, - FLAMECHART_FRAME_HEIGHT, - EVENT_ROW_HEIGHT_FIXED, -} from './constants'; - -/** - * Returns a hover context info object containing the `ReactEvent` currently - * being hovered over. - * - * NOTE: Assumes that the events are all in a row, and that the cursor is - * already known to be in this row; this function only compares the X positions - * of the cursor and events. - */ -function getHoveredReactEvent( - data: $ReadOnly, - panAndZoomState: PanAndZoomState, -): ReactHoverContextInfo | null { - const {canvasMouseX} = panAndZoomState; - const {events} = data; - - // Because data ranges may overlap, we want to find the last intersecting item. - // This will always be the one on "top" (the one the user is hovering over). - for (let index = events.length - 1; index >= 0; index--) { - const event = events[index]; - const {timestamp} = event; - - const eventX = timestampToPosition(timestamp, panAndZoomState); - const startX = eventX - REACT_EVENT_SIZE / 2; - const stopX = eventX + REACT_EVENT_SIZE / 2; - if (canvasMouseX >= startX && canvasMouseX <= stopX) { - return { - event, - flamechartNode: null, - measure: null, - lane: null, - data, - }; - } - } - - return null; -} - -/** - * Returns a hover context info object containing the `ReactMeasure` currently - * being hovered over. - */ -function getHoveredReactMeasure( - data: $ReadOnly, - panAndZoomState: PanAndZoomState, - stackSectionBaseY: number, -): ReactHoverContextInfo | null { - const {canvasMouseX, canvasMouseY, offsetY} = panAndZoomState; - - // Identify the lane being hovered over - const adjustedCanvasMouseY = canvasMouseY - stackSectionBaseY + offsetY; - let laneMinY = 0; - let lane = null; - for ( - let laneIndex: ReactLane = 0; - laneIndex < REACT_TOTAL_NUM_LANES; - laneIndex++ - ) { - const laneHeight = getLaneHeight(data, laneIndex); - if ( - adjustedCanvasMouseY >= laneMinY && - adjustedCanvasMouseY <= laneMinY + laneHeight - ) { - lane = laneIndex; - break; - } - laneMinY += laneHeight; - } - - if (lane === null) { - return null; - } - - // Find the measure in `lane` being hovered over. - // - // Because data ranges may overlap, we want to find the last intersecting item. - // This will always be the one on "top" (the one the user is hovering over). - const {measures} = data; - for (let index = measures.length - 1; index >= 0; index--) { - const measure = measures[index]; - if (!measure.lanes.includes(lane)) { - continue; - } - - const {duration, timestamp} = measure; - const pointerTime = positionToTimestamp(canvasMouseX, panAndZoomState); - - if (pointerTime >= timestamp && pointerTime <= timestamp + duration) { - return { - event: null, - flamechartNode: null, - measure, - lane, - data, - }; - } - } - - return null; -} - -/** - * Returns a hover context info object containing the `FlamechartFrame` - * currently being hovered over. - */ -function getHoveredFlamechartEvent( - data: $ReadOnly, - flamechart: $ReadOnly, - panAndZoomState: PanAndZoomState, - stackSectionBaseY: number, -): ReactHoverContextInfo | null { - const {canvasMouseX, canvasMouseY, offsetY} = panAndZoomState; - - const layerIndex = Math.floor( - (canvasMouseY + offsetY - stackSectionBaseY) / FLAMECHART_FRAME_HEIGHT, - ); - const layer = flamechart.layers[layerIndex]; - - if (!layer) { - return null; - } - - let startIndex = 0; - let stopIndex = layer.length - 1; - while (startIndex <= stopIndex) { - const currentIndex = Math.floor((startIndex + stopIndex) / 2); - const flamechartNode = layer[currentIndex]; - - const {end, start} = flamechartNode; - - const width = durationToWidth((end - start) / 1000, panAndZoomState); - const x = Math.floor(timestampToPosition(start / 1000, panAndZoomState)); - - if (x <= canvasMouseX && x + width >= canvasMouseX) { - return { - event: null, - flamechartNode, - measure: null, - lane: null, - data, - }; - } - - if (x > canvasMouseX) { - stopIndex = currentIndex - 1; - } else { - startIndex = currentIndex + 1; - } - } - - return null; -} - -/** - * Returns a hover context object if the cursor is hovering over a React - * event/measure or a Flamechart node, otherwise returns null. - */ -export function getHoveredEvent( - schedulerCanvasHeight: number, - data: $ReadOnly, - flamechart: $ReadOnly, - panAndZoomState: PanAndZoomState, -): ReactHoverContextInfo | null { - const {canvasMouseY, offsetY} = panAndZoomState; - - // These variables keep track of the current vertical stack sections' base and - // max Y coordinates. For example, if we're at the React event row, these are - // what the values represent: - // ┌----------------------------------- - // | t⁰ t¹ t² ... - // ├---------------------------------- <- stackSectionBaseY - // | - // | - // | - // ├---------------------------------- <- stackSectionMaxY - // | - // | - // | - // ├---------------------------------- - // | - // | - // | - // └---------------------------------- - let stackSectionBaseY: number; - let stackSectionMaxY: number = 0; - - // Header section: do nothing - stackSectionBaseY = stackSectionMaxY; - stackSectionMaxY += HEADER_HEIGHT_FIXED; - if (canvasMouseY < stackSectionMaxY) { - return null; - } - - // ReactEvent row - stackSectionBaseY = stackSectionMaxY; - stackSectionMaxY += EVENT_ROW_HEIGHT_FIXED; - if (canvasMouseY + offsetY < stackSectionMaxY) { - return getHoveredReactEvent(data, panAndZoomState); - } - - // ReactMeasure lanes - stackSectionBaseY = stackSectionMaxY; - stackSectionMaxY += schedulerCanvasHeight; - if (canvasMouseY + offsetY < stackSectionMaxY) { - return getHoveredReactMeasure(data, panAndZoomState, stackSectionBaseY); - } - - // Flamechart area - stackSectionBaseY = stackSectionMaxY; - return getHoveredFlamechartEvent( - data, - flamechart, - panAndZoomState, - stackSectionBaseY, - ); -} diff --git a/src/canvas/renderCanvas.js b/src/canvas/renderCanvas.js deleted file mode 100644 index 3737c1c4ddd6c..0000000000000 --- a/src/canvas/renderCanvas.js +++ /dev/null @@ -1,563 +0,0 @@ -// @flow - -import type { - FlamechartData, - ReactHoverContextInfo, - ReactLane, - ReactProfilerData, -} from '../types'; -import type {PanAndZoomState} from '../util/usePanAndZoom'; - -import memoize from 'memoize-one'; - -import { - durationToWidth, - positionToTimestamp, - timestampToPosition, -} from '../util/usePanAndZoom'; - -import { - getCanvasContext, - getTimeTickInterval, - trimFlamegraphText, - getLaneHeight, -} from './canvasUtils'; - -import { - COLORS, - MARKER_FONT_SIZE, - MARKER_TEXT_PADDING, - MARKER_HEIGHT, - MARKER_TICK_HEIGHT, - REACT_GUTTER_SIZE, - REACT_WORK_SIZE, - REACT_WORK_BORDER_SIZE, - FLAMECHART_FONT_SIZE, - FLAMECHART_FRAME_HEIGHT, - FLAMECHART_TEXT_PADDING, - LABEL_FIXED_WIDTH, - HEADER_HEIGHT_FIXED, - REACT_EVENT_SIZE, - EVENT_SIZE, - REACT_EVENT_ROW_PADDING, - EVENT_ROW_HEIGHT_FIXED, -} from './constants'; -import {REACT_TOTAL_NUM_LANES} from '../constants'; - -// The canvas we're rendering looks a little like the outline below. -// Left labels mark different scheduler REACT_PRIORITIES, -// and top labels mark different times (based on how long the data runs and how zoomed in we are). -// The content in the bottom right area is scrollable, but the top/left labels are fixed. -// -// ┌----------------------------------- -// | t⁰ t¹ t² ... -// ├-------------┬--------------------- -// | unscheduled ┋ -// ├-------------┼--------------------- -// | high ┋ -// ├-------------┼--------------------- -// | normal ┋ -// ├-------------┼--------------------- -// | low ┋ -// ├-------------┼--------------------- -// | ┋ -// | ┋ -// | ┋ -// └-------------┴--------------------- -// -// Because everything we draw on a canvas is drawn on top of what was already there, -// we render the graph in several passes, each pass creating a layer: -// ,──────── -// axis labels → / -// ,──/ -// profiling data → / '─────────── -// ,─ / -// axis marker lines → / '──────────────── -// ,─ / -// background fills → / '───────────────────── -// / -// '────────────────────────── -// - -// TODO: (windowing, optimization) We can avoid rendering offscreen data in many -// of the render* functions in this file. - -function renderBackgroundFills(context, canvasWidth, canvasHeight) { - // Fill the canvas with the background color - context.fillStyle = COLORS.BACKGROUND; - context.fillRect(0, 0, canvasWidth, canvasHeight); -} - -/** - * Render React events from `data` in a single row. - * - * The React events will be rendered into the canvas `context` of dimensions - * `canvasWidth`x`canvasHeight`, starting at `canvasStartY`. The events will be - * offset by pan and zoom `state`. Optionally with a highlighted - * `hoveredEvent`. - * - * @see renderSingleReactEvent - */ -function renderReactEventRow( - context, - events, - state, - hoveredEvent, - canvasWidth, - canvasHeight, - canvasStartY, -): number { - const {offsetY} = state; - - // Draw events - const baseY = canvasStartY + REACT_EVENT_ROW_PADDING; - events.forEach(event => { - const showHoverHighlight = hoveredEvent && hoveredEvent.event === event; - renderSingleReactEvent( - context, - state, - event, - canvasWidth, - baseY, - offsetY, - showHoverHighlight, - ); - }); - - // Draw the hovered and/or selected items on top so they stand out. - // This is helpful if there are multiple (overlapping) items close to each other. - if (hoveredEvent !== null && hoveredEvent.event !== null) { - renderSingleReactEvent( - context, - state, - hoveredEvent.event, - canvasWidth, - baseY, - offsetY, - true, - ); - } - - // Render bottom border - context.fillStyle = COLORS.PRIORITY_BORDER; - context.fillRect( - 0, - Math.floor( - canvasStartY + EVENT_ROW_HEIGHT_FIXED - offsetY - REACT_WORK_BORDER_SIZE, - ), - canvasWidth, - REACT_WORK_BORDER_SIZE, - ); - - return canvasStartY + EVENT_ROW_HEIGHT_FIXED; -} - -/** - * Render a single `ReactEvent` as a circle in the canvas. - * - * @see renderReactEventRow - */ -function renderSingleReactEvent( - context, - state, - event, - canvasWidth, - baseY, - panOffsetY, - showHoverHighlight, -) { - const {timestamp, type} = event; - - const x = timestampToPosition(timestamp, state); - if (x + EVENT_SIZE / 2 < 0 || canvasWidth < x) { - return; // Not in view - } - - let fillStyle = null; - - switch (type) { - case 'schedule-render': - case 'schedule-state-update': - case 'schedule-force-update': - if (event.isCascading) { - fillStyle = showHoverHighlight - ? COLORS.REACT_SCHEDULE_CASCADING_HOVER - : COLORS.REACT_SCHEDULE_CASCADING; - } else { - fillStyle = showHoverHighlight - ? COLORS.REACT_SCHEDULE_HOVER - : COLORS.REACT_SCHEDULE; - } - break; - case 'suspense-suspend': - case 'suspense-resolved': - case 'suspense-rejected': - fillStyle = showHoverHighlight - ? COLORS.REACT_SUSPEND_HOVER - : COLORS.REACT_SUSPEND; - break; - default: - console.warn(`Unexpected event type "${type}"`); - break; - } - - if (fillStyle !== null) { - const circumference = REACT_EVENT_SIZE; - const y = baseY + REACT_EVENT_SIZE / 2 - panOffsetY; - - context.beginPath(); - context.fillStyle = fillStyle; - context.arc(x, y, circumference / 2, 0, 2 * Math.PI); - context.fill(); - } -} - -/** - * Render React measures from `data` in parallel lanes. - * - * The React measures will be rendered into the canvas `context` of dimensions - * `canvasWidth`x`canvasHeight`, starting at `canvasStartY`. The measures will - * be offset by pan and zoom `state`. Optionally with a highlighted - * `hoveredEvent`. - * - * @see renderSingleReactMeasure - */ -function renderReactMeasures( - context, - data, - state, - hoveredEvent, - canvasWidth, - canvasHeight, - canvasStartY, -): number { - const {offsetY} = state; - - // TODO: Compute lanes to render from data? Or just use getLaneHeight to skip lanes - const lanesToRender: ReactLane[] = Array.from( - Array(REACT_TOTAL_NUM_LANES).keys(), - ); - - let laneMinY = canvasStartY; - - // Render lanes background. - // TODO: Figure out a way not to compute total height twice - const schedulerAreaHeight = lanesToRender.reduce( - (height, lane) => height + getLaneHeight(data, lane), - 0, - ); - context.fillStyle = COLORS.PRIORITY_BACKGROUND; - context.fillRect( - 0, - Math.floor(canvasStartY - offsetY), - canvasWidth, - schedulerAreaHeight, - ); - - lanesToRender.forEach(lane => { - const baseY = laneMinY + REACT_GUTTER_SIZE; - - data.measures - // TODO: Optimization: precompute this so that we don't filter this array |lanesToRender| times - .filter(measure => measure.lanes.includes(lane)) - .forEach(measure => { - const showHoverHighlight = - hoveredEvent && hoveredEvent.measure === measure; - const showGroupHighlight = - hoveredEvent && - hoveredEvent.measure && - hoveredEvent.measure.batchUID === measure.batchUID; - renderSingleReactMeasure( - context, - state, - measure, - canvasWidth, - baseY, - showGroupHighlight, - showHoverHighlight, - ); - }); - - laneMinY += getLaneHeight(data, lane); - - // Render bottom border - context.fillStyle = COLORS.PRIORITY_BORDER; - context.fillRect( - 0, - Math.floor(laneMinY - offsetY - REACT_WORK_BORDER_SIZE), - canvasWidth, - REACT_WORK_BORDER_SIZE, - ); - }); - - return laneMinY; -} - -/** - * Render a single `ReactMeasure` as a bar in the canvas. - * - * @see renderReactMeasures - */ -function renderSingleReactMeasure( - context, - state, - measure, - canvasWidth, - baseY, - showGroupHighlight, - showHoverHighlight, -) { - const {timestamp, type, duration} = measure; - const {offsetY} = state; - - let fillStyle = null; - let hoveredFillStyle = null; - let groupSelectedFillStyle = null; - - // We could change the max to 0 and just skip over rendering anything that small, - // but this has the effect of making the chart look very empty when zoomed out. - // So long as perf is okay- it might be best to err on the side of showing things. - const width = durationToWidth(duration, state); - if (width <= 0) { - return; // Too small to render at this zoom level - } - - const x = timestampToPosition(timestamp, state); - if (x + width < 0 || canvasWidth < x) { - return; // Not in view - } - - switch (type) { - case 'commit': - fillStyle = COLORS.REACT_COMMIT; - hoveredFillStyle = COLORS.REACT_COMMIT_HOVER; - groupSelectedFillStyle = COLORS.REACT_COMMIT_SELECTED; - break; - case 'render-idle': - // We could render idle time as diagonal hashes. - // This looks nicer when zoomed in, but not so nice when zoomed out. - // color = context.createPattern(getIdlePattern(), 'repeat'); - fillStyle = COLORS.REACT_IDLE; - hoveredFillStyle = COLORS.REACT_IDLE_HOVER; - groupSelectedFillStyle = COLORS.REACT_IDLE_SELECTED; - break; - case 'render': - fillStyle = COLORS.REACT_RENDER; - hoveredFillStyle = COLORS.REACT_RENDER_HOVER; - groupSelectedFillStyle = COLORS.REACT_RENDER_SELECTED; - break; - case 'layout-effects': - fillStyle = COLORS.REACT_LAYOUT_EFFECTS; - hoveredFillStyle = COLORS.REACT_LAYOUT_EFFECTS_HOVER; - groupSelectedFillStyle = COLORS.REACT_LAYOUT_EFFECTS_SELECTED; - break; - case 'passive-effects': - fillStyle = COLORS.REACT_PASSIVE_EFFECTS; - hoveredFillStyle = COLORS.REACT_PASSIVE_EFFECTS_HOVER; - groupSelectedFillStyle = COLORS.REACT_PASSIVE_EFFECTS_SELECTED; - break; - default: - throw new Error(`Unexpected measure type "${type}"`); - } - - const y = baseY - offsetY; - - context.fillStyle = showHoverHighlight - ? hoveredFillStyle - : showGroupHighlight - ? groupSelectedFillStyle - : fillStyle; - context.fillRect( - Math.floor(x), - Math.floor(y), - Math.floor(width), - REACT_WORK_SIZE, - ); -} - -function renderFlamechart( - context, - flamechart, - state, - hoveredEvent, - canvasWidth, - canvasHeight, - /** y coord on canvas to start painting at */ - canvasStartY, -) { - context.textAlign = 'left'; - context.textBaseline = 'middle'; - context.font = `${FLAMECHART_FONT_SIZE}px sans-serif`; - - for (let i = 0; i < flamechart.layers.length; i++) { - const nodes = flamechart.layers[i]; - - const layerY = Math.floor(canvasStartY + i * FLAMECHART_FRAME_HEIGHT); - if ( - layerY + FLAMECHART_FRAME_HEIGHT < HEADER_HEIGHT_FIXED || - canvasHeight < layerY - ) { - continue; // Not in view - } - - for (let j = 0; j < nodes.length; j++) { - const {end, node, start} = nodes[j]; - const {name} = node.frame; - - const showHoverHighlight = - hoveredEvent && hoveredEvent.flamechartNode === nodes[j]; - - const width = durationToWidth((end - start) / 1000, state); - if (width <= 0) { - continue; // Too small to render at this zoom level - } - - const x = Math.floor(timestampToPosition(start / 1000, state)); - if (x + width < 0 || canvasWidth < x) { - continue; // Not in view - } - - context.fillStyle = showHoverHighlight - ? COLORS.FLAME_GRAPH_HOVER - : COLORS.FLAME_GRAPH; - - context.fillRect( - x, - layerY, - Math.floor(width - REACT_WORK_BORDER_SIZE), - Math.floor(FLAMECHART_FRAME_HEIGHT - REACT_WORK_BORDER_SIZE), - ); - - if (width > FLAMECHART_TEXT_PADDING * 2) { - const trimmedName = trimFlamegraphText( - context, - name, - width - FLAMECHART_TEXT_PADDING * 2 + (x < 0 ? x : 0), - ); - if (trimmedName !== null) { - context.fillStyle = COLORS.PRIORITY_LABEL; - context.fillText( - trimmedName, - x + FLAMECHART_TEXT_PADDING - (x < 0 ? x : 0), - layerY + FLAMECHART_FRAME_HEIGHT / 2, - ); - } - } - } - } -} - -function renderAxisMarkers( - context, - state, - canvasWidth, - panOffsetX, - panZoomLevel, -) { - context.fillStyle = COLORS.BACKGROUND; - context.fillRect(0, 0, canvasWidth, HEADER_HEIGHT_FIXED); - - context.fillStyle = COLORS.PRIORITY_BORDER; - context.fillRect(0, MARKER_HEIGHT, canvasWidth, REACT_WORK_BORDER_SIZE); - - // Charting data renders within this region of pixels as "scrollable" content. - // Time markers (top) and priority labels (left) are fixed content. - const scrollableCanvasWidth = canvasWidth - LABEL_FIXED_WIDTH; - - const interval = getTimeTickInterval(panZoomLevel); - const intervalSize = interval * panZoomLevel; - const firstIntervalPosition = - 0 - panOffsetX + Math.floor(panOffsetX / intervalSize) * intervalSize; - - for ( - let i = firstIntervalPosition; - i < scrollableCanvasWidth; - i += intervalSize - ) { - if (i > 0) { - const markerTimestamp = positionToTimestamp(i + LABEL_FIXED_WIDTH, state); - const markerLabel = Math.round(markerTimestamp); - - const x = LABEL_FIXED_WIDTH + i; - - context.fillStyle = COLORS.PRIORITY_BORDER; - context.fillRect( - x, - MARKER_HEIGHT - MARKER_TICK_HEIGHT, - REACT_WORK_BORDER_SIZE, - MARKER_TICK_HEIGHT, - ); - - context.fillStyle = COLORS.TIME_MARKER_LABEL; - context.textAlign = 'right'; - context.textBaseline = 'middle'; - context.font = `${MARKER_FONT_SIZE}px sans-serif`; - context.fillText( - `${markerLabel}ms`, - x - MARKER_TEXT_PADDING, - MARKER_HEIGHT / 2, - ); - } - } -} - -// TODO Passing "state" directly breaks memoization for e.g. mouse moves -export const renderCanvas = memoize( - ( - data: $ReadOnly, - flamechart: $ReadOnly, - canvas: HTMLCanvasElement, - canvasWidth: number, - canvasHeight: number, - state: $ReadOnly, - hoveredEvent: $ReadOnly | null, - ) => { - const {offsetX, offsetY, zoomLevel} = state; - - const context = getCanvasContext(canvas, canvasHeight, canvasWidth, true); - - renderBackgroundFills(context, canvasWidth, canvasHeight); - - let schedulerAreaEndY = HEADER_HEIGHT_FIXED; - - schedulerAreaEndY = renderReactEventRow( - context, - data.events, - state, - hoveredEvent, - canvasWidth, - canvasHeight, - schedulerAreaEndY, - ); - - schedulerAreaEndY = renderReactMeasures( - context, - data, - state, - hoveredEvent, - canvasWidth, - canvasHeight, - // Time markers do not scroll off screen; they are always rendered at a - // fixed vertical position. - schedulerAreaEndY, - ); - - // Flame graph data renders below the prioritized React data. - // TODO Timestamp alignment is off by a few hundred me from our user timing marks; why? - renderFlamechart( - context, - flamechart, - state, - hoveredEvent, - canvasWidth, - canvasHeight, - schedulerAreaEndY - offsetY, - ); - - // TOP: Time markers - // Time markers do not scroll off screen; they are always rendered at a fixed vertical position. - // Render them last, on top of everything else, to account for things scrolled beneath them. - // Draw time marker text on top of the priority groupings - renderAxisMarkers(context, state, canvasWidth, offsetX, zoomLevel); - }, -); diff --git a/src/canvas/views/FlamegraphView.js b/src/canvas/views/FlamegraphView.js new file mode 100644 index 0000000000000..603bc1b40adb2 --- /dev/null +++ b/src/canvas/views/FlamegraphView.js @@ -0,0 +1,246 @@ +// @flow + +import type {FlamechartFrame} from '@elg/speedscope'; +import type {Interaction, HoverInteraction} from '../../useCanvasInteraction'; +import type {FlamechartData, ReactProfilerData} from '../../types'; +import type {Rect, Size} from '../../layout'; + +import { + View, + Surface, + rectContainsPoint, + rectEqualToRect, + rectIntersectsRect, + rectIntersectionWithRect, +} from '../../layout'; +import { + durationToWidth, + positioningScaleFactor, + timestampToPosition, + trimFlamegraphText, +} from '../canvasUtils'; +import { + COLORS, + FLAMECHART_FONT_SIZE, + FLAMECHART_FRAME_HEIGHT, + FLAMECHART_TEXT_PADDING, + REACT_WORK_BORDER_SIZE, +} from '../constants'; + +export class FlamegraphView extends View { + flamechart: FlamechartData; + profilerData: ReactProfilerData; + intrinsicSize: Size; + + hoveredFlamechartNode: FlamechartFrame | null = null; + onHover: ((node: FlamechartFrame | null) => void) | null = null; + + constructor( + surface: Surface, + frame: Rect, + flamechart: FlamechartData, + profilerData: ReactProfilerData, + ) { + super(surface, frame); + this.flamechart = flamechart; + this.profilerData = profilerData; + this.intrinsicSize = { + width: this.profilerData.duration, + height: this.flamechart.getLayers().length * FLAMECHART_FRAME_HEIGHT, + }; + } + + desiredSize() { + return this.intrinsicSize; + } + + setHoveredFlamechartNode(hoveredFlamechartNode: FlamechartFrame | null) { + if (this.hoveredFlamechartNode === hoveredFlamechartNode) { + return; + } + this.hoveredFlamechartNode = hoveredFlamechartNode; + this.setNeedsDisplay(); + } + + draw(context: CanvasRenderingContext2D) { + const { + frame, + flamechart, + hoveredFlamechartNode, + intrinsicSize, + visibleArea, + } = this; + + context.fillStyle = COLORS.BACKGROUND; + context.fillRect( + visibleArea.origin.x, + visibleArea.origin.y, + visibleArea.size.width, + visibleArea.size.height, + ); + + context.textAlign = 'left'; + context.textBaseline = 'middle'; + context.font = `${FLAMECHART_FONT_SIZE}px sans-serif`; + + const scaleFactor = positioningScaleFactor(intrinsicSize.width, frame); + + for (let i = 0; i < flamechart.getLayers().length; i++) { + const nodes = flamechart.getLayers()[i]; + + const layerY = Math.floor(frame.origin.y + i * FLAMECHART_FRAME_HEIGHT); + if ( + layerY + FLAMECHART_FRAME_HEIGHT < visibleArea.origin.y || + visibleArea.origin.y + visibleArea.size.height < layerY + ) { + continue; // Not in view + } + + for (let j = 0; j < nodes.length; j++) { + const {end, node, start} = nodes[j]; + const {name} = node.frame; + + const width = durationToWidth((end - start) / 1000, scaleFactor); + if (width < 1) { + continue; // Too small to render at this zoom level + } + + const x = Math.floor( + timestampToPosition(start / 1000, scaleFactor, frame), + ); + const nodeRect: Rect = { + origin: {x, y: layerY}, + size: { + width: Math.floor(width - REACT_WORK_BORDER_SIZE), + height: Math.floor( + FLAMECHART_FRAME_HEIGHT - REACT_WORK_BORDER_SIZE, + ), + }, + }; + if (!rectIntersectsRect(nodeRect, visibleArea)) { + continue; // Not in view + } + + const showHoverHighlight = hoveredFlamechartNode === nodes[j]; + context.fillStyle = showHoverHighlight + ? COLORS.FLAME_GRAPH_HOVER + : COLORS.FLAME_GRAPH; + + const drawableRect = rectIntersectionWithRect(nodeRect, visibleArea); + context.fillRect( + drawableRect.origin.x, + drawableRect.origin.y, + drawableRect.size.width, + drawableRect.size.height, + ); + + if (width > FLAMECHART_TEXT_PADDING * 2) { + const trimmedName = trimFlamegraphText( + context, + name, + width - FLAMECHART_TEXT_PADDING * 2 + (x < 0 ? x : 0), + ); + + if (trimmedName !== null) { + context.fillStyle = COLORS.PRIORITY_LABEL; + + // Prevent text from being drawn outside `viewableArea` + const textOverflowsViewableArea = !rectEqualToRect( + drawableRect, + nodeRect, + ); + if (textOverflowsViewableArea) { + context.save(); + context.rect( + drawableRect.origin.x, + drawableRect.origin.y, + drawableRect.size.width, + drawableRect.size.height, + ); + context.clip(); + } + + context.fillText( + trimmedName, + x + FLAMECHART_TEXT_PADDING - (x < 0 ? x : 0), + layerY + FLAMECHART_FRAME_HEIGHT / 2, + ); + + if (textOverflowsViewableArea) { + context.restore(); + } + } + } + } + } + } + + /** + * @private + */ + handleHover(interaction: HoverInteraction) { + const {flamechart, frame, intrinsicSize, onHover, visibleArea} = this; + if (!onHover) { + return; + } + + const {location} = interaction.payload; + if (!rectContainsPoint(location, visibleArea)) { + onHover(null); + return; + } + + // Identify the layer being hovered over + const adjustedCanvasMouseY = location.y - frame.origin.y; + const layerIndex = Math.floor( + adjustedCanvasMouseY / FLAMECHART_FRAME_HEIGHT, + ); + if (layerIndex < 0 || layerIndex >= flamechart.getLayers().length) { + onHover(null); + return; + } + const layer = flamechart.getLayers()[layerIndex]; + + if (!layer) { + return null; + } + + // Find the node being hovered over. + const scaleFactor = positioningScaleFactor(intrinsicSize.width, frame); + let startIndex = 0; + let stopIndex = layer.length - 1; + while (startIndex <= stopIndex) { + const currentIndex = Math.floor((startIndex + stopIndex) / 2); + const flamechartNode = layer[currentIndex]; + + const {end, start} = flamechartNode; + + const width = durationToWidth((end - start) / 1000, scaleFactor); + + const x = Math.floor( + timestampToPosition(start / 1000, scaleFactor, frame), + ); + + if (x <= location.x && x + width >= location.x) { + onHover(flamechartNode); + return; + } + + if (x > location.x) { + stopIndex = currentIndex - 1; + } else { + startIndex = currentIndex + 1; + } + } + + onHover(null); + } + + handleInteractionAndPropagateToSubviews(interaction: Interaction) { + switch (interaction.type) { + case 'hover': + this.handleHover(interaction); + break; + } + } +} diff --git a/src/canvas/views/ReactEventsView.js b/src/canvas/views/ReactEventsView.js new file mode 100644 index 0000000000000..9eff893965cd7 --- /dev/null +++ b/src/canvas/views/ReactEventsView.js @@ -0,0 +1,246 @@ +// @flow + +import type {Interaction, HoverInteraction} from '../../useCanvasInteraction'; +import type {ReactEvent, ReactProfilerData} from '../../types'; +import type {Rect, Size} from '../../layout'; + +import { + positioningScaleFactor, + timestampToPosition, + positionToTimestamp, + widthToDuration, +} from '../canvasUtils'; +import { + View, + Surface, + rectContainsPoint, + rectIntersectsRect, + rectIntersectionWithRect, +} from '../../layout'; +import { + COLORS, + EVENT_ROW_HEIGHT_FIXED, + REACT_EVENT_ROW_PADDING, + REACT_EVENT_SIZE, + REACT_WORK_BORDER_SIZE, +} from '../constants'; + +export class ReactEventsView extends View { + profilerData: ReactProfilerData; + intrinsicSize: Size; + + hoveredEvent: ReactEvent | null = null; + onHover: ((event: ReactEvent | null) => void) | null = null; + + constructor(surface: Surface, frame: Rect, profilerData: ReactProfilerData) { + super(surface, frame); + this.profilerData = profilerData; + + this.intrinsicSize = { + width: this.profilerData.duration, + height: EVENT_ROW_HEIGHT_FIXED, + }; + } + + desiredSize() { + return this.intrinsicSize; + } + + setHoveredEvent(hoveredEvent: ReactEvent | null) { + if (this.hoveredEvent === hoveredEvent) { + return; + } + this.hoveredEvent = hoveredEvent; + this.setNeedsDisplay(); + } + + /** + * Draw a single `ReactEvent` as a circle in the canvas. + */ + drawSingleReactEvent( + context: CanvasRenderingContext2D, + rect: Rect, + event: ReactEvent, + baseY: number, + scaleFactor: number, + showHoverHighlight: boolean, + ) { + const {frame} = this; + const {timestamp, type} = event; + + const x = timestampToPosition(timestamp, scaleFactor, frame); + const radius = REACT_EVENT_SIZE / 2; + const eventRect: Rect = { + origin: { + x: x - radius, + y: baseY, + }, + size: {width: REACT_EVENT_SIZE, height: REACT_EVENT_SIZE}, + }; + if (!rectIntersectsRect(eventRect, rect)) { + return; // Not in view + } + + let fillStyle = null; + + switch (type) { + case 'schedule-render': + case 'schedule-state-update': + case 'schedule-force-update': + if (event.isCascading) { + fillStyle = showHoverHighlight + ? COLORS.REACT_SCHEDULE_CASCADING_HOVER + : COLORS.REACT_SCHEDULE_CASCADING; + } else { + fillStyle = showHoverHighlight + ? COLORS.REACT_SCHEDULE_HOVER + : COLORS.REACT_SCHEDULE; + } + break; + case 'suspense-suspend': + case 'suspense-resolved': + case 'suspense-rejected': + fillStyle = showHoverHighlight + ? COLORS.REACT_SUSPEND_HOVER + : COLORS.REACT_SUSPEND; + break; + default: + console.warn(`Unexpected event type "${type}"`); + break; + } + + if (fillStyle !== null) { + const y = eventRect.origin.y + radius; + + context.beginPath(); + context.fillStyle = fillStyle; + context.arc(x, y, radius, 0, 2 * Math.PI); + context.fill(); + } + } + + draw(context: CanvasRenderingContext2D) { + const { + frame, + profilerData: {events}, + hoveredEvent, + visibleArea, + } = this; + + context.fillStyle = COLORS.BACKGROUND; + context.fillRect( + visibleArea.origin.x, + visibleArea.origin.y, + visibleArea.size.width, + visibleArea.size.height, + ); + + // Draw events + const baseY = frame.origin.y + REACT_EVENT_ROW_PADDING; + const scaleFactor = positioningScaleFactor(this.intrinsicSize.width, frame); + + events.forEach(event => { + if (event === hoveredEvent) { + return; + } + this.drawSingleReactEvent( + context, + visibleArea, + event, + baseY, + scaleFactor, + false, + ); + }); + + // Draw the hovered and/or selected items on top so they stand out. + // This is helpful if there are multiple (overlapping) items close to each other. + if (hoveredEvent !== null) { + this.drawSingleReactEvent( + context, + visibleArea, + hoveredEvent, + baseY, + scaleFactor, + true, + ); + } + + // Render bottom border. + // Propose border rect, check if intersects with `rect`, draw intersection. + const borderFrame: Rect = { + origin: { + x: frame.origin.x, + y: frame.origin.y + EVENT_ROW_HEIGHT_FIXED - REACT_WORK_BORDER_SIZE, + }, + size: { + width: frame.size.width, + height: REACT_WORK_BORDER_SIZE, + }, + }; + if (rectIntersectsRect(borderFrame, visibleArea)) { + const borderDrawableRect = rectIntersectionWithRect( + borderFrame, + visibleArea, + ); + context.fillStyle = COLORS.PRIORITY_BORDER; + context.fillRect( + borderDrawableRect.origin.x, + borderDrawableRect.origin.y, + borderDrawableRect.size.width, + borderDrawableRect.size.height, + ); + } + } + + /** + * @private + */ + handleHover(interaction: HoverInteraction) { + const {frame, onHover, visibleArea} = this; + if (!onHover) { + return; + } + + const {location} = interaction.payload; + if (!rectContainsPoint(location, visibleArea)) { + onHover(null); + return; + } + + const { + profilerData: {events}, + } = this; + const scaleFactor = positioningScaleFactor(this.intrinsicSize.width, frame); + const hoverTimestamp = positionToTimestamp(location.x, scaleFactor, frame); + const eventTimestampAllowance = widthToDuration( + REACT_EVENT_SIZE / 2, + scaleFactor, + ); + + // Because data ranges may overlap, we want to find the last intersecting item. + // This will always be the one on "top" (the one the user is hovering over). + for (let index = events.length - 1; index >= 0; index--) { + const event = events[index]; + const {timestamp} = event; + + if ( + timestamp - eventTimestampAllowance <= hoverTimestamp && + hoverTimestamp <= timestamp + eventTimestampAllowance + ) { + onHover(event); + return; + } + } + + onHover(null); + } + + handleInteractionAndPropagateToSubviews(interaction: Interaction) { + switch (interaction.type) { + case 'hover': + this.handleHover(interaction); + break; + } + } +} diff --git a/src/canvas/views/ReactMeasuresView.js b/src/canvas/views/ReactMeasuresView.js new file mode 100644 index 0000000000000..a77d9c4c9ee10 --- /dev/null +++ b/src/canvas/views/ReactMeasuresView.js @@ -0,0 +1,304 @@ +// @flow + +import type {Interaction, HoverInteraction} from '../../useCanvasInteraction'; +import type {ReactLane, ReactMeasure, ReactProfilerData} from '../../types'; +import type {Rect, Size} from '../../layout'; + +import { + durationToWidth, + positioningScaleFactor, + positionToTimestamp, + timestampToPosition, +} from '../canvasUtils'; +import { + View, + Surface, + rectContainsPoint, + rectIntersectsRect, + rectIntersectionWithRect, +} from '../../layout'; + +import {COLORS, REACT_WORK_BORDER_SIZE, REACT_WORK_SIZE} from '../constants'; +import {REACT_TOTAL_NUM_LANES} from '../../constants'; + +const REACT_LANE_HEIGHT = REACT_WORK_SIZE + REACT_WORK_BORDER_SIZE; + +export class ReactMeasuresView extends View { + profilerData: ReactProfilerData; + intrinsicSize: Size; + + lanesToRender: ReactLane[]; + laneToMeasures: Map; + + hoveredMeasure: ReactMeasure | null = null; + onHover: ((measure: ReactMeasure | null) => void) | null = null; + + constructor(surface: Surface, frame: Rect, profilerData: ReactProfilerData) { + super(surface, frame); + this.profilerData = profilerData; + this.performPreflightComputations(); + } + + performPreflightComputations() { + this.lanesToRender = []; + this.laneToMeasures = new Map(); + + for (let lane: ReactLane = 0; lane < REACT_TOTAL_NUM_LANES; lane++) { + // Hide lanes without any measures + const measuresForLane = this.profilerData.measures.filter(measure => + measure.lanes.includes(lane), + ); + if (measuresForLane.length) { + this.lanesToRender.push(lane); + this.laneToMeasures.set(lane, measuresForLane); + } + } + + this.intrinsicSize = { + width: this.profilerData.duration, + height: this.lanesToRender.length * REACT_LANE_HEIGHT, + }; + } + + desiredSize() { + return this.intrinsicSize; + } + + setHoveredMeasure(hoveredMeasure: ReactMeasure | null) { + if (this.hoveredMeasure === hoveredMeasure) { + return; + } + this.hoveredMeasure = hoveredMeasure; + this.setNeedsDisplay(); + } + + /** + * Draw a single `ReactMeasure` as a bar in the canvas. + */ + drawSingleReactMeasure( + context: CanvasRenderingContext2D, + rect: Rect, + measure: ReactMeasure, + baseY: number, + scaleFactor: number, + showGroupHighlight: boolean, + showHoverHighlight: boolean, + ) { + const {frame} = this; + const {timestamp, type, duration} = measure; + + let fillStyle = null; + let hoveredFillStyle = null; + let groupSelectedFillStyle = null; + + // We could change the max to 0 and just skip over rendering anything that small, + // but this has the effect of making the chart look very empty when zoomed out. + // So long as perf is okay- it might be best to err on the side of showing things. + const width = durationToWidth(duration, scaleFactor); + if (width <= 0) { + return; // Too small to render at this zoom level + } + + const x = timestampToPosition(timestamp, scaleFactor, frame); + const measureRect: Rect = { + origin: {x, y: baseY}, + size: {width, height: REACT_WORK_SIZE}, + }; + if (!rectIntersectsRect(measureRect, rect)) { + return; // Not in view + } + + switch (type) { + case 'commit': + fillStyle = COLORS.REACT_COMMIT; + hoveredFillStyle = COLORS.REACT_COMMIT_HOVER; + groupSelectedFillStyle = COLORS.REACT_COMMIT_SELECTED; + break; + case 'render-idle': + // We could render idle time as diagonal hashes. + // This looks nicer when zoomed in, but not so nice when zoomed out. + // color = context.createPattern(getIdlePattern(), 'repeat'); + fillStyle = COLORS.REACT_IDLE; + hoveredFillStyle = COLORS.REACT_IDLE_HOVER; + groupSelectedFillStyle = COLORS.REACT_IDLE_SELECTED; + break; + case 'render': + fillStyle = COLORS.REACT_RENDER; + hoveredFillStyle = COLORS.REACT_RENDER_HOVER; + groupSelectedFillStyle = COLORS.REACT_RENDER_SELECTED; + break; + case 'layout-effects': + fillStyle = COLORS.REACT_LAYOUT_EFFECTS; + hoveredFillStyle = COLORS.REACT_LAYOUT_EFFECTS_HOVER; + groupSelectedFillStyle = COLORS.REACT_LAYOUT_EFFECTS_SELECTED; + break; + case 'passive-effects': + fillStyle = COLORS.REACT_PASSIVE_EFFECTS; + hoveredFillStyle = COLORS.REACT_PASSIVE_EFFECTS_HOVER; + groupSelectedFillStyle = COLORS.REACT_PASSIVE_EFFECTS_SELECTED; + break; + default: + throw new Error(`Unexpected measure type "${type}"`); + } + + const drawableRect = rectIntersectionWithRect(measureRect, rect); + context.fillStyle = showHoverHighlight + ? hoveredFillStyle + : showGroupHighlight + ? groupSelectedFillStyle + : fillStyle; + context.fillRect( + drawableRect.origin.x, + drawableRect.origin.y, + drawableRect.size.width, + drawableRect.size.height, + ); + } + + draw(context: CanvasRenderingContext2D) { + const { + frame, + hoveredMeasure, + lanesToRender, + laneToMeasures, + visibleArea, + } = this; + + context.fillStyle = COLORS.PRIORITY_BACKGROUND; + context.fillRect( + visibleArea.origin.x, + visibleArea.origin.y, + visibleArea.size.width, + visibleArea.size.height, + ); + + const scaleFactor = positioningScaleFactor(this.intrinsicSize.width, frame); + + for (let i = 0; i < lanesToRender.length; i++) { + const lane = lanesToRender[i]; + const baseY = frame.origin.y + i * REACT_LANE_HEIGHT; + const measuresForLane = laneToMeasures.get(lane); + + if (!measuresForLane) { + throw new Error( + 'No measures found for a React lane! This is a bug in this profiler tool. Please file an issue.', + ); + } + + // Draw measures + for (let j = 0; j < measuresForLane.length; j++) { + const measure = measuresForLane[j]; + const showHoverHighlight = hoveredMeasure === measure; + const showGroupHighlight = + !!hoveredMeasure && hoveredMeasure.batchUID === measure.batchUID; + + this.drawSingleReactMeasure( + context, + visibleArea, + measure, + baseY, + scaleFactor, + showGroupHighlight, + showHoverHighlight, + ); + } + + // Render bottom border + const borderFrame: Rect = { + origin: { + x: frame.origin.x, + y: + frame.origin.y + + (i + 1) * REACT_LANE_HEIGHT - + REACT_WORK_BORDER_SIZE, + }, + size: { + width: frame.size.width, + height: REACT_WORK_BORDER_SIZE, + }, + }; + if (rectIntersectsRect(borderFrame, visibleArea)) { + const borderDrawableRect = rectIntersectionWithRect( + borderFrame, + visibleArea, + ); + context.fillStyle = COLORS.PRIORITY_BORDER; + context.fillRect( + borderDrawableRect.origin.x, + borderDrawableRect.origin.y, + borderDrawableRect.size.width, + borderDrawableRect.size.height, + ); + } + } + } + + /** + * @private + */ + handleHover(interaction: HoverInteraction) { + const { + frame, + intrinsicSize, + lanesToRender, + laneToMeasures, + onHover, + visibleArea, + } = this; + if (!onHover) { + return; + } + + const {location} = interaction.payload; + if (!rectContainsPoint(location, visibleArea)) { + onHover(null); + return; + } + + // Identify the lane being hovered over + const adjustedCanvasMouseY = location.y - frame.origin.y; + const renderedLaneIndex = Math.floor( + adjustedCanvasMouseY / REACT_LANE_HEIGHT, + ); + if (renderedLaneIndex < 0 || renderedLaneIndex >= lanesToRender.length) { + onHover(null); + return; + } + const lane = lanesToRender[renderedLaneIndex]; + + // Find the measure in `lane` being hovered over. + // + // Because data ranges may overlap, we want to find the last intersecting item. + // This will always be the one on "top" (the one the user is hovering over). + const scaleFactor = positioningScaleFactor(intrinsicSize.width, frame); + const hoverTimestamp = positionToTimestamp(location.x, scaleFactor, frame); + const measures = laneToMeasures.get(lane); + if (!measures) { + onHover(null); + return; + } + + for (let index = measures.length - 1; index >= 0; index--) { + const measure = measures[index]; + const {duration, timestamp} = measure; + + if ( + hoverTimestamp >= timestamp && + hoverTimestamp <= timestamp + duration + ) { + onHover(measure); + return; + } + } + + onHover(null); + } + + handleInteractionAndPropagateToSubviews(interaction: Interaction) { + switch (interaction.type) { + case 'hover': + this.handleHover(interaction); + break; + } + } +} diff --git a/src/canvas/views/TimeAxisMarkersView.js b/src/canvas/views/TimeAxisMarkersView.js new file mode 100644 index 0000000000000..6d97ab1abef2e --- /dev/null +++ b/src/canvas/views/TimeAxisMarkersView.js @@ -0,0 +1,160 @@ +// @flow + +import type {Rect, Size} from '../../layout'; + +import { + durationToWidth, + positioningScaleFactor, + positionToTimestamp, + timestampToPosition, +} from '../canvasUtils'; +import { + View, + Surface, + rectIntersectsRect, + rectIntersectionWithRect, +} from '../../layout'; +import { + COLORS, + HEADER_HEIGHT_FIXED, + INTERVAL_TIMES, + LABEL_FIXED_WIDTH, + MARKER_FONT_SIZE, + MARKER_HEIGHT, + MARKER_TEXT_PADDING, + MARKER_TICK_HEIGHT, + MIN_INTERVAL_SIZE_PX, + REACT_WORK_BORDER_SIZE, +} from '../constants'; + +export class TimeAxisMarkersView extends View { + totalDuration: number; + intrinsicSize: Size; + + constructor(surface: Surface, frame: Rect, totalDuration: number) { + super(surface, frame); + this.totalDuration = totalDuration; + this.intrinsicSize = { + width: this.totalDuration, + height: HEADER_HEIGHT_FIXED, + }; + } + + desiredSize() { + return this.intrinsicSize; + } + + // Time mark intervals vary based on the current zoom range and the time it represents. + // In Chrome, these seem to range from 70-140 pixels wide. + // Time wise, they represent intervals of e.g. 1s, 500ms, 200ms, 100ms, 50ms, 20ms. + // Based on zoom, we should determine which amount to actually show. + getTimeTickInterval(scaleFactor: number): number { + for (let i = 0; i < INTERVAL_TIMES.length; i++) { + const currentInterval = INTERVAL_TIMES[i]; + const intervalWidth = durationToWidth(currentInterval, scaleFactor); + if (intervalWidth > MIN_INTERVAL_SIZE_PX) { + return currentInterval; + } + } + return INTERVAL_TIMES[0]; + } + + draw(context: CanvasRenderingContext2D) { + const {frame, intrinsicSize, visibleArea} = this; + const clippedFrame = { + origin: frame.origin, + size: { + width: frame.size.width, + height: intrinsicSize.height, + }, + }; + const drawableRect = rectIntersectionWithRect(clippedFrame, visibleArea); + + // Clear background + context.fillStyle = COLORS.BACKGROUND; + context.fillRect( + drawableRect.origin.x, + drawableRect.origin.y, + drawableRect.size.width, + drawableRect.size.height, + ); + + const scaleFactor = positioningScaleFactor( + intrinsicSize.width, + clippedFrame, + ); + const interval = this.getTimeTickInterval(scaleFactor); + const firstIntervalTimestamp = + Math.ceil( + positionToTimestamp( + drawableRect.origin.x - LABEL_FIXED_WIDTH, + scaleFactor, + clippedFrame, + ) / interval, + ) * interval; + + for ( + let markerTimestamp = firstIntervalTimestamp; + true; + markerTimestamp += interval + ) { + if (markerTimestamp <= 0) { + continue; // Timestamps < are probably a bug; markers at 0 are ugly. + } + + const x = timestampToPosition(markerTimestamp, scaleFactor, clippedFrame); + if (x > drawableRect.origin.x + drawableRect.size.width) { + break; // Not in view + } + + const markerLabel = Math.round(markerTimestamp); + + context.fillStyle = COLORS.PRIORITY_BORDER; + context.fillRect( + x, + drawableRect.origin.y + MARKER_HEIGHT - MARKER_TICK_HEIGHT, + REACT_WORK_BORDER_SIZE, + MARKER_TICK_HEIGHT, + ); + + context.fillStyle = COLORS.TIME_MARKER_LABEL; + context.textAlign = 'right'; + context.textBaseline = 'middle'; + context.font = `${MARKER_FONT_SIZE}px sans-serif`; + context.fillText( + `${markerLabel}ms`, + x - MARKER_TEXT_PADDING, + MARKER_HEIGHT / 2, + ); + } + + // Render bottom border. + // Propose border rect, check if intersects with `rect`, draw intersection. + const borderFrame: Rect = { + origin: { + x: clippedFrame.origin.x, + y: + clippedFrame.origin.y + + clippedFrame.size.height - + REACT_WORK_BORDER_SIZE, + }, + size: { + width: clippedFrame.size.width, + height: REACT_WORK_BORDER_SIZE, + }, + }; + if (rectIntersectsRect(borderFrame, visibleArea)) { + const borderDrawableRect = rectIntersectionWithRect( + borderFrame, + visibleArea, + ); + context.fillStyle = COLORS.PRIORITY_BORDER; + context.fillRect( + borderDrawableRect.origin.x, + borderDrawableRect.origin.y, + borderDrawableRect.size.width, + borderDrawableRect.size.height, + ); + } + } +} diff --git a/src/canvas/views/index.js b/src/canvas/views/index.js new file mode 100644 index 0000000000000..04dfba8a12a9e --- /dev/null +++ b/src/canvas/views/index.js @@ -0,0 +1,6 @@ +// @flow + +export * from './FlamegraphView'; +export * from './ReactEventsView'; +export * from './ReactMeasuresView'; +export * from './TimeAxisMarkersView'; diff --git a/src/layout/HorizontalPanAndZoomView.js b/src/layout/HorizontalPanAndZoomView.js new file mode 100644 index 0000000000000..23dd46348e4ef --- /dev/null +++ b/src/layout/HorizontalPanAndZoomView.js @@ -0,0 +1,299 @@ +// @flow + +import type { + Interaction, + HorizontalPanStartInteraction, + HorizontalPanMoveInteraction, + HorizontalPanEndInteraction, + WheelPlainInteraction, + WheelWithShiftInteraction, + WheelWithControlInteraction, + WheelWithMetaInteraction, +} from '../useCanvasInteraction'; +import type {Rect} from './geometry'; + +import {Surface} from './Surface'; +import {View} from './View'; +import {rectContainsPoint} from './geometry'; +import { + MIN_ZOOM_LEVEL, + MAX_ZOOM_LEVEL, + MOVE_WHEEL_DELTA_THRESHOLD, +} from '../canvas/constants'; // TODO: Remove external dependency + +type HorizontalPanAndZoomState = {| + /** Horizontal offset; positive in the left direction */ + offsetX: number, + zoomLevel: number, +|}; + +function panAndZoomStatesAreEqual( + state1: HorizontalPanAndZoomState, + state2: HorizontalPanAndZoomState, +): boolean { + return ( + state1.offsetX === state2.offsetX && state1.zoomLevel === state2.zoomLevel + ); +} + +function clamp(min: number, max: number, value: number): number { + if (Number.isNaN(min) || Number.isNaN(max) || Number.isNaN(value)) { + throw new Error( + `Clamp was called with NaN. Args: min: ${min}, max: ${max}, value: ${value}.`, + ); + } + return Math.min(max, Math.max(min, value)); +} + +function zoomLevelAndIntrinsicWidthToFrameWidth( + zoomLevel: number, + intrinsicWidth: number, +): number { + return intrinsicWidth * zoomLevel; +} + +export class HorizontalPanAndZoomView extends View { + contentView: View; + intrinsicContentWidth: number; + + panAndZoomState: HorizontalPanAndZoomState = { + offsetX: 0, + zoomLevel: 0.25, + }; + + stateDeriver: ( + state: HorizontalPanAndZoomState, + ) => HorizontalPanAndZoomState = state => state; + + onStateChange: (state: HorizontalPanAndZoomState) => void = () => {}; + + constructor( + surface: Surface, + frame: Rect, + contentView: View, + intrinsicContentWidth: number, + stateDeriver?: ( + state: HorizontalPanAndZoomState, + ) => HorizontalPanAndZoomState, + onStateChange?: (state: HorizontalPanAndZoomState) => void, + ) { + super(surface, frame); + this.contentView = contentView; + contentView.superview = this; + this.intrinsicContentWidth = intrinsicContentWidth; + if (stateDeriver) this.stateDeriver = stateDeriver; + if (onStateChange) this.onStateChange = onStateChange; + } + + setNeedsDisplay() { + super.setNeedsDisplay(); + this.contentView.setNeedsDisplay(); + } + + setFrame(newFrame: Rect) { + super.setFrame(newFrame); + + // Revalidate panAndZoomState + this.updateState(this.panAndZoomState); + } + + layoutSubviews() { + const {offsetX, zoomLevel} = this.panAndZoomState; + const proposedFrame = { + origin: { + x: this.frame.origin.x + offsetX, + y: this.frame.origin.y, + }, + size: { + width: zoomLevelAndIntrinsicWidthToFrameWidth( + zoomLevel, + this.intrinsicContentWidth, + ), + height: this.frame.size.height, + }, + }; + this.contentView.setFrame(proposedFrame); + this.contentView.setVisibleArea(this.visibleArea); + } + + draw(context: CanvasRenderingContext2D) { + this.contentView.displayIfNeeded(context); + } + + isPanning = false; + + handleHorizontalPanStart(interaction: HorizontalPanStartInteraction) { + if (rectContainsPoint(interaction.payload.location, this.frame)) { + this.isPanning = true; + } + } + + handleHorizontalPanMove(interaction: HorizontalPanMoveInteraction) { + if (!this.isPanning) { + return; + } + const {offsetX} = this.panAndZoomState; + const {movementX} = interaction.payload.event; + this.updateState({ + ...this.panAndZoomState, + offsetX: offsetX + movementX, + }); + } + + handleHorizontalPanEnd(interaction: HorizontalPanEndInteraction) { + if (this.isPanning) { + this.isPanning = false; + } + } + + handleWheelPlain(interaction: WheelPlainInteraction) { + const { + location, + event: {deltaX, deltaY}, + } = interaction.payload; + if (!rectContainsPoint(location, this.frame)) { + return; // Not scrolling on view + } + + const absDeltaX = Math.abs(deltaX); + const absDeltaY = Math.abs(deltaY); + if (absDeltaY > absDeltaX) { + return; // Scrolling vertically + } + + if (absDeltaX < MOVE_WHEEL_DELTA_THRESHOLD) { + return; + } + + this.updateState({ + ...this.panAndZoomState, + offsetX: this.panAndZoomState.offsetX - deltaX, + }); + } + + handleWheelZoom( + interaction: + | WheelWithShiftInteraction + | WheelWithControlInteraction + | WheelWithMetaInteraction, + ) { + const { + location, + event: {deltaY}, + } = interaction.payload; + if (!rectContainsPoint(location, this.frame)) { + return; // Not scrolling on view + } + + const absDeltaY = Math.abs(deltaY); + if (absDeltaY < MOVE_WHEEL_DELTA_THRESHOLD) { + return; + } + + const zoomClampedState = this.clampedProposedStateZoomLevel({ + ...this.panAndZoomState, + zoomLevel: this.panAndZoomState.zoomLevel * (1 + 0.005 * -deltaY), + }); + + // Determine where the mouse is, and adjust the offset so that point stays + // centered after zooming. + const oldMouseXInFrame = location.x - zoomClampedState.offsetX; + const fractionalMouseX = + oldMouseXInFrame / this.contentView.frame.size.width; + const newContentWidth = zoomLevelAndIntrinsicWidthToFrameWidth( + zoomClampedState.zoomLevel, + this.intrinsicContentWidth, + ); + const newMouseXInFrame = fractionalMouseX * newContentWidth; + + const offsetAdjustedState = this.clampedProposedStateOffsetX({ + ...zoomClampedState, + offsetX: location.x - newMouseXInFrame, + }); + + this.updateState(offsetAdjustedState); + } + + handleInteractionAndPropagateToSubviews(interaction: Interaction) { + switch (interaction.type) { + case 'horizontal-pan-start': + this.handleHorizontalPanStart(interaction); + break; + case 'horizontal-pan-move': + this.handleHorizontalPanMove(interaction); + break; + case 'horizontal-pan-end': + this.handleHorizontalPanEnd(interaction); + break; + case 'wheel-plain': + this.handleWheelPlain(interaction); + break; + case 'wheel-shift': + case 'wheel-control': + case 'wheel-meta': + this.handleWheelZoom(interaction); + break; + } + this.contentView.handleInteractionAndPropagateToSubviews(interaction); + } + + /** + * @private + */ + updateState(proposedState: HorizontalPanAndZoomState) { + const clampedState = this.stateDeriver( + this.clampedProposedState(proposedState), + ); + if (!panAndZoomStatesAreEqual(clampedState, this.panAndZoomState)) { + this.panAndZoomState = clampedState; + this.onStateChange(this.panAndZoomState); + this.setNeedsDisplay(); + } + } + + /** + * @private + */ + clampedProposedStateZoomLevel( + proposedState: HorizontalPanAndZoomState, + ): HorizontalPanAndZoomState { + // Content-based min zoom level to ensure that contentView's width >= our width. + const minContentBasedZoomLevel = + this.frame.size.width / this.intrinsicContentWidth; + const minZoomLevel = Math.max(MIN_ZOOM_LEVEL, minContentBasedZoomLevel); + return { + ...proposedState, + zoomLevel: clamp(minZoomLevel, MAX_ZOOM_LEVEL, proposedState.zoomLevel), + }; + } + + /** + * @private + */ + clampedProposedStateOffsetX( + proposedState: HorizontalPanAndZoomState, + ): HorizontalPanAndZoomState { + const newContentWidth = zoomLevelAndIntrinsicWidthToFrameWidth( + proposedState.zoomLevel, + this.intrinsicContentWidth, + ); + return { + ...proposedState, + offsetX: clamp( + -(newContentWidth - this.frame.size.width), + 0, + proposedState.offsetX, + ), + }; + } + + /** + * @private + */ + clampedProposedState( + proposedState: HorizontalPanAndZoomState, + ): HorizontalPanAndZoomState { + const zoomClampedState = this.clampedProposedStateZoomLevel(proposedState); + return this.clampedProposedStateOffsetX(zoomClampedState); + } +} diff --git a/src/layout/StaticLayoutView.js b/src/layout/StaticLayoutView.js new file mode 100644 index 0000000000000..3d00912f51127 --- /dev/null +++ b/src/layout/StaticLayoutView.js @@ -0,0 +1,90 @@ +// @flow + +import type {Interaction} from '../useCanvasInteraction'; +import type {Rect} from './geometry'; + +import {Surface} from './Surface'; +import {View} from './View'; +import { + rectIntersectsRect, + rectIntersectionWithRect, + zeroRect, +} from './geometry'; + +export type Layouter = (views: View[], containingFrame: Rect) => void; + +export const layeredLayout: Layouter = (views, frame) => + views.forEach(subview => { + subview.setFrame(frame); + }); + +export const verticallyStackedLayout: Layouter = (views, frame) => { + let currentY = frame.origin.y; + views.forEach(view => { + const desiredSize = view.desiredSize(); + const height = desiredSize + ? desiredSize.height + : frame.size.height - currentY; + const proposedFrame = { + origin: {x: frame.origin.x, y: currentY}, + size: {width: frame.size.width, height}, + }; + view.setFrame(proposedFrame); + currentY += height; + }); +}; + +export class StaticLayoutView extends View { + subviews: View[] = []; + layouter: Layouter; + + constructor( + surface: Surface, + frame: Rect, + layouter: Layouter, + subviews: View[], + ) { + super(surface, frame); + this.layouter = layouter; + subviews.forEach(subview => this.addSubview(subview)); + } + + setNeedsDisplay() { + super.setNeedsDisplay(); + this.subviews.forEach(subview => subview.setNeedsDisplay()); + } + + addSubview(view: View) { + this.subviews.push(view); + view.superview = this; + } + + layoutSubviews() { + const {frame, layouter, subviews, visibleArea} = this; + layouter(subviews, frame); + subviews.forEach(subview => { + if (rectIntersectsRect(visibleArea, subview.frame)) { + subview.setVisibleArea( + rectIntersectionWithRect(visibleArea, subview.frame), + ); + } else { + subview.setVisibleArea(zeroRect); + } + }); + } + + draw(context: CanvasRenderingContext2D) { + const {subviews, visibleArea} = this; + subviews.forEach(subview => { + if (rectIntersectsRect(visibleArea, subview.visibleArea)) { + subview.displayIfNeeded(context); + } + }); + } + + handleInteractionAndPropagateToSubviews(interaction: Interaction) { + this.subviews.forEach(subview => + subview.handleInteractionAndPropagateToSubviews(interaction), + ); + } +} diff --git a/src/layout/Surface.js b/src/layout/Surface.js new file mode 100644 index 0000000000000..0df492da83922 --- /dev/null +++ b/src/layout/Surface.js @@ -0,0 +1,51 @@ +// @flow + +import type {Interaction} from '../useCanvasInteraction'; +import type {Size} from './geometry'; + +import {getCanvasContext} from '../canvas/canvasUtils'; + +import {View} from './View'; +import {zeroPoint} from './geometry'; + +export class Surface { + rootView: ?View; + context: ?CanvasRenderingContext2D; + canvasSize: ?Size; + + setCanvas(canvas: HTMLCanvasElement, canvasSize: Size) { + this.context = getCanvasContext( + canvas, + canvasSize.height, + canvasSize.width, + ); + this.canvasSize = canvasSize; + + if (this.rootView) { + this.rootView.setNeedsDisplay(); + } + } + + displayIfNeeded() { + const {rootView, canvasSize, context} = this; + if (!rootView || !context || !canvasSize) { + return; + } + rootView.setFrame({ + origin: zeroPoint, + size: canvasSize, + }); + rootView.setVisibleArea({ + origin: zeroPoint, + size: canvasSize, + }); + rootView.displayIfNeeded(context); + } + + handleInteraction(interaction: Interaction) { + if (!this.rootView) { + return; + } + this.rootView.handleInteractionAndPropagateToSubviews(interaction); + } +} diff --git a/src/layout/VerticalScrollView.js b/src/layout/VerticalScrollView.js new file mode 100644 index 0000000000000..906e7f377a2eb --- /dev/null +++ b/src/layout/VerticalScrollView.js @@ -0,0 +1,196 @@ +// @flow + +import type { + Interaction, + VerticalPanStartInteraction, + VerticalPanMoveInteraction, + VerticalPanEndInteraction, + WheelPlainInteraction, +} from '../useCanvasInteraction'; +import type {Rect} from './geometry'; + +import {Surface} from './Surface'; +import {View} from './View'; +import {rectContainsPoint} from './geometry'; +import {MOVE_WHEEL_DELTA_THRESHOLD} from '../canvas/constants'; // TODO: Remove external dependency + +type VerticalScrollState = {| + offsetY: number, +|}; + +function scrollStatesAreEqual( + state1: VerticalScrollState, + state2: VerticalScrollState, +): boolean { + return state1.offsetY === state2.offsetY; +} + +// TODO: Deduplicate +function clamp(min: number, max: number, value: number): number { + if (Number.isNaN(min) || Number.isNaN(max) || Number.isNaN(value)) { + throw new Error( + `Clamp was called with NaN. Args: min: ${min}, max: ${max}, value: ${value}.`, + ); + } + return Math.min(max, Math.max(min, value)); +} + +export class VerticalScrollView extends View { + contentView: View; + intrinsicContentHeight: number; + + scrollState: VerticalScrollState = { + offsetY: 0, + }; + + stateDeriver: (state: VerticalScrollState) => VerticalScrollState = state => + state; + + onStateChange: (state: VerticalScrollState) => void = () => {}; + + constructor( + surface: Surface, + frame: Rect, + contentView: View, + intrinsicContentHeight: number, + stateDeriver?: (state: VerticalScrollState) => VerticalScrollState, + onStateChange?: (state: VerticalScrollState) => void, + ) { + super(surface, frame); + this.contentView = contentView; + contentView.superview = this; + this.intrinsicContentHeight = intrinsicContentHeight; + if (stateDeriver) this.stateDeriver = stateDeriver; + if (onStateChange) this.onStateChange = onStateChange; + } + + setNeedsDisplay() { + super.setNeedsDisplay(); + this.contentView.setNeedsDisplay(); + } + + setFrame(newFrame: Rect) { + super.setFrame(newFrame); + + // Revalidate scrollState + this.updateState(this.scrollState); + } + + layoutSubviews() { + const {offsetY} = this.scrollState; + const proposedFrame = { + origin: { + x: this.frame.origin.x, + y: this.frame.origin.y + offsetY, + }, + size: { + width: this.frame.size.width, + height: this.intrinsicContentHeight, + }, + }; + this.contentView.setFrame(proposedFrame); + this.contentView.setVisibleArea(this.visibleArea); + } + + draw(context: CanvasRenderingContext2D) { + this.contentView.displayIfNeeded(context); + } + + isPanning = false; + + handleVerticalPanStart(interaction: VerticalPanStartInteraction) { + if (rectContainsPoint(interaction.payload.location, this.frame)) { + this.isPanning = true; + } + } + + handleVerticalPanMove(interaction: VerticalPanMoveInteraction) { + if (!this.isPanning) { + return; + } + const {offsetY} = this.scrollState; + const {movementY} = interaction.payload.event; + this.updateState({ + ...this.scrollState, + offsetY: offsetY + movementY, + }); + } + + handleVerticalPanEnd(interaction: VerticalPanEndInteraction) { + if (this.isPanning) { + this.isPanning = false; + } + } + + handleWheelPlain(interaction: WheelPlainInteraction) { + const { + location, + event: {deltaX, deltaY}, + } = interaction.payload; + if (!rectContainsPoint(location, this.frame)) { + return; // Not scrolling on view + } + + const absDeltaX = Math.abs(deltaX); + const absDeltaY = Math.abs(deltaY); + if (absDeltaX > absDeltaY) { + return; // Scrolling horizontally + } + + if (absDeltaY < MOVE_WHEEL_DELTA_THRESHOLD) { + return; + } + + this.updateState({ + ...this.scrollState, + offsetY: this.scrollState.offsetY - deltaY, + }); + } + + handleInteractionAndPropagateToSubviews(interaction: Interaction) { + switch (interaction.type) { + case 'vertical-pan-start': + this.handleVerticalPanStart(interaction); + break; + case 'vertical-pan-move': + this.handleVerticalPanMove(interaction); + break; + case 'vertical-pan-end': + this.handleVerticalPanEnd(interaction); + break; + case 'wheel-plain': + this.handleWheelPlain(interaction); + break; + } + this.contentView.handleInteractionAndPropagateToSubviews(interaction); + } + + /** + * @private + */ + updateState(proposedState: VerticalScrollState) { + const clampedState = this.stateDeriver( + this.clampedProposedState(proposedState), + ); + if (!scrollStatesAreEqual(clampedState, this.scrollState)) { + this.scrollState = clampedState; + this.onStateChange(this.scrollState); + this.setNeedsDisplay(); + } + } + + /** + * @private + */ + clampedProposedState( + proposedState: VerticalScrollState, + ): VerticalScrollState { + return { + offsetY: clamp( + -(this.contentView.frame.size.height - this.frame.size.height), + 0, + proposedState.offsetY, + ), + }; + } +} diff --git a/src/layout/View.js b/src/layout/View.js new file mode 100644 index 0000000000000..d34c80aec3566 --- /dev/null +++ b/src/layout/View.js @@ -0,0 +1,113 @@ +// @flow + +import type {Interaction} from '../useCanvasInteraction'; +import type {Rect, Size} from './geometry'; + +import {Surface} from './Surface'; +import { + rectIntersectsRect, + rectEqualToRect, + sizeIsEmpty, + sizeIsValid, + zeroRect, +} from './geometry'; + +export class View { + surface: Surface; + + frame: Rect; + visibleArea: Rect; + + superview: ?View; + + /** Whether this view needs to be drawn. */ + needsDisplay = true; + /** Whether the heirarchy below this view has subviews that need display. */ + subviewsNeedDisplay = false; + + constructor(surface: Surface, frame: Rect, visibleArea: Rect = frame) { + this.surface = surface; + this.frame = frame; + this.visibleArea = visibleArea; + } + + /** + * Invalidates view's contents. + * + * Downward propagating; once called, all subviews of this view should also + * be invalidated. + * + * Subclasses with subviews should override this method and call + * `setNeedsDisplay` on its subviews. + */ + setNeedsDisplay() { + this.needsDisplay = true; + if (this.superview) { + this.superview.setSubviewsNeedDisplay(); + } + } + + /** + * Informs superview that it has subviews that need to be drawn. + * + * Upward propagating; once called, all superviews of this view should also + * have `subviewsNeedDisplay` = true. + */ + setSubviewsNeedDisplay() { + this.subviewsNeedDisplay = true; + if (this.superview) { + this.superview.setSubviewsNeedDisplay(); + } + } + + setFrame(newFrame: Rect) { + if (!rectEqualToRect(this.frame, newFrame)) { + this.frame = newFrame; + if (sizeIsValid(newFrame.size)) { + this.frame = newFrame; + } else { + this.frame = zeroRect; + } + this.setNeedsDisplay(); + } + } + + setVisibleArea(newVisibleArea: Rect) { + if (!rectEqualToRect(this.visibleArea, newVisibleArea)) { + if (sizeIsValid(newVisibleArea.size)) { + this.visibleArea = newVisibleArea; + } else { + this.visibleArea = zeroRect; + } + this.setNeedsDisplay(); + } + } + + desiredSize(): ?Size {} + + /** + * Layout self and subviews. + * + * Call `setNeedsDisplay` if we are to redraw. + * + * To be overwritten by subclasses. + */ + layoutSubviews() {} + + displayIfNeeded(context: CanvasRenderingContext2D) { + if ( + (this.needsDisplay || this.subviewsNeedDisplay) && + rectIntersectsRect(this.frame, this.visibleArea) && + !sizeIsEmpty(this.visibleArea.size) + ) { + this.layoutSubviews(); + if (this.needsDisplay) this.needsDisplay = false; + if (this.subviewsNeedDisplay) this.subviewsNeedDisplay = false; + this.draw(context); + } + } + + draw(context: CanvasRenderingContext2D) {} + + handleInteractionAndPropagateToSubviews(interaction: Interaction): ?boolean {} +} diff --git a/src/layout/geometry.js b/src/layout/geometry.js new file mode 100644 index 0000000000000..57622279d217c --- /dev/null +++ b/src/layout/geometry.js @@ -0,0 +1,88 @@ +// @flow + +type MutablePoint = {x: number, y: number}; +type MutableSize = {width: number, height: number}; + +export type Point = $ReadOnly; +export type Size = $ReadOnly; +export type Rect = $ReadOnly<{origin: Point, size: Size}>; + +export const zeroPoint: Point = Object.freeze({x: 0, y: 0}); +export const zeroSize: Size = Object.freeze({width: 0, height: 0}); +export const zeroRect: Rect = Object.freeze({ + origin: zeroPoint, + size: zeroSize, +}); + +export function pointEqualToPoint(point1: Point, point2: Point): boolean { + return point1.x === point2.x && point1.y === point2.y; +} + +export function sizeEqualToSize(size1: Size, size2: Size): boolean { + return size1.width === size2.width && size1.height === size2.height; +} + +export function rectEqualToRect(rect1: Rect, rect2: Rect): boolean { + return ( + pointEqualToPoint(rect1.origin, rect2.origin) && + sizeEqualToSize(rect1.size, rect2.size) + ); +} + +export function sizeIsValid({width, height}: Size): boolean { + return width >= 0 && height >= 0; +} + +export function sizeIsEmpty({width, height}: Size): boolean { + return width <= 0 || height <= 0; +} + +function rectToBoundaryCoordinates( + rect: Rect, +): [number, number, number, number] { + const top = rect.origin.y; + const right = rect.origin.x + rect.size.width; + const bottom = rect.origin.y + rect.size.height; + const left = rect.origin.x; + return [top, right, bottom, left]; +} + +export function rectIntersectsRect(rect1: Rect, rect2: Rect): boolean { + const [top1, right1, bottom1, left1] = rectToBoundaryCoordinates(rect1); + const [top2, right2, bottom2, left2] = rectToBoundaryCoordinates(rect2); + return !( + right1 < left2 || + right2 < left1 || + bottom1 < top2 || + bottom2 < top1 + ); +} + +/** + * Prerequisite: rect1 must intersect with rect2. + */ +export function rectIntersectionWithRect(rect1: Rect, rect2: Rect): Rect { + const [top1, right1, bottom1, left1] = rectToBoundaryCoordinates(rect1); + const [top2, right2, bottom2, left2] = rectToBoundaryCoordinates(rect2); + + const intersectleft = Math.max(left1, left2); + const intersectRight = Math.min(right1, right2); + const intersectTop = Math.max(top1, top2); + const intersectBottom = Math.min(bottom1, bottom2); + + return { + origin: { + x: intersectleft, + y: intersectTop, + }, + size: { + width: intersectRight - intersectleft, + height: intersectBottom - intersectTop, + }, + }; +} + +export function rectContainsPoint({x, y}: Point, rect: Rect): boolean { + const [top, right, bottom, left] = rectToBoundaryCoordinates(rect); + return left <= x && x <= right && top <= y && y <= bottom; +} diff --git a/src/layout/index.js b/src/layout/index.js new file mode 100644 index 0000000000000..df9f5d6e9b675 --- /dev/null +++ b/src/layout/index.js @@ -0,0 +1,8 @@ +// @flow + +export * from './geometry'; +export * from './HorizontalPanAndZoomView'; +export * from './StaticLayoutView'; +export * from './Surface'; +export * from './VerticalScrollView'; +export * from './View'; diff --git a/src/types.js b/src/types.js index f3444ba77bb71..4a52abef29686 100644 --- a/src/types.js +++ b/src/types.js @@ -97,7 +97,6 @@ export type ReactProfilerData = {| export type ReactHoverContextInfo = {| event: ReactEvent | null, measure: ReactMeasure | null, - lane: ReactLane | null, data: $ReadOnly | null, flamechartNode: FlamechartFrame | null, |}; diff --git a/src/useCanvasInteraction.js b/src/useCanvasInteraction.js new file mode 100644 index 0000000000000..0b2136faa952a --- /dev/null +++ b/src/useCanvasInteraction.js @@ -0,0 +1,234 @@ +// @flow + +import type {Point} from './layout'; + +import {useEffect} from 'react'; + +export type VerticalPanStartInteraction = {| + type: 'vertical-pan-start', + payload: {| + event: MouseEvent, + location: Point, + |}, +|}; +export type VerticalPanMoveInteraction = {| + type: 'vertical-pan-move', + payload: {| + event: MouseEvent, + location: Point, + |}, +|}; +export type VerticalPanEndInteraction = {| + type: 'vertical-pan-end', + payload: {| + event: MouseEvent, + location: Point, + |}, +|}; +export type HorizontalPanStartInteraction = {| + type: 'horizontal-pan-start', + payload: {| + event: MouseEvent, + location: Point, + |}, +|}; +export type HorizontalPanMoveInteraction = {| + type: 'horizontal-pan-move', + payload: {| + event: MouseEvent, + location: Point, + |}, +|}; +export type HorizontalPanEndInteraction = {| + type: 'horizontal-pan-end', + payload: {| + event: MouseEvent, + location: Point, + |}, +|}; +export type HoverInteraction = {| + type: 'hover', + payload: {| + event: MouseEvent, + location: Point, + |}, +|}; +export type WheelPlainInteraction = {| + type: 'wheel-plain', + payload: {| + event: WheelEvent, + location: Point, + |}, +|}; +export type WheelWithShiftInteraction = {| + type: 'wheel-shift', + payload: {| + event: WheelEvent, + location: Point, + |}, +|}; +export type WheelWithControlInteraction = {| + type: 'wheel-control', + payload: {| + event: WheelEvent, + location: Point, + |}, +|}; +export type WheelWithMetaInteraction = {| + type: 'wheel-meta', + payload: {| + event: WheelEvent, + location: Point, + |}, +|}; + +export type Interaction = + | VerticalPanStartInteraction + | VerticalPanMoveInteraction + | VerticalPanEndInteraction + | HorizontalPanStartInteraction + | HorizontalPanMoveInteraction + | HorizontalPanEndInteraction + | HoverInteraction + | WheelPlainInteraction + | WheelWithShiftInteraction + | WheelWithControlInteraction + | WheelWithMetaInteraction; + +export function useCanvasInteraction( + canvasRef: {|current: HTMLCanvasElement | null|}, + interactor: (interaction: Interaction) => void, +) { + useEffect(() => { + const canvas = canvasRef.current; + + function localToCanvasCoordinates(localCoordinates: Point): Point { + if (!canvas) { + return localCoordinates; + } + const canvasRect = canvas.getBoundingClientRect(); + return { + x: localCoordinates.x - canvasRect.left, + y: localCoordinates.y - canvasRect.top, + }; + } + + if (!(canvas instanceof HTMLCanvasElement)) { + console.error('canvas is not a HTMLCanvasElement!', canvas); + return; + } + + const onCanvasMouseDown: MouseEventHandler = event => { + interactor({ + type: 'horizontal-pan-start', + payload: { + event, + location: localToCanvasCoordinates({x: event.x, y: event.y}), + }, + }); + interactor({ + type: 'vertical-pan-start', + payload: { + event, + location: localToCanvasCoordinates({x: event.x, y: event.y}), + }, + }); + }; + + const onCanvasMouseMove: MouseEventHandler = event => { + interactor({ + type: 'horizontal-pan-move', + payload: { + event, + location: localToCanvasCoordinates({x: event.x, y: event.y}), + }, + }); + interactor({ + type: 'vertical-pan-move', + payload: { + event, + location: localToCanvasCoordinates({x: event.x, y: event.y}), + }, + }); + interactor({ + type: 'hover', + payload: { + event, + location: localToCanvasCoordinates({x: event.x, y: event.y}), + }, + }); + }; + + const onDocumentMouseUp: MouseEventHandler = event => { + interactor({ + type: 'horizontal-pan-end', + payload: { + event, + location: localToCanvasCoordinates({x: event.x, y: event.y}), + }, + }); + interactor({ + type: 'vertical-pan-end', + payload: { + event, + location: localToCanvasCoordinates({x: event.x, y: event.y}), + }, + }); + }; + + const onCanvasWheel: WheelEventHandler = event => { + event.preventDefault(); + event.stopPropagation(); + + if (event.shiftKey) { + interactor({ + type: 'wheel-shift', + payload: { + event, + location: localToCanvasCoordinates({x: event.x, y: event.y}), + }, + }); + } else if (event.ctrlKey) { + interactor({ + type: 'wheel-control', + payload: { + event, + location: localToCanvasCoordinates({x: event.x, y: event.y}), + }, + }); + } else if (event.metaKey) { + interactor({ + type: 'wheel-meta', + payload: { + event, + location: localToCanvasCoordinates({x: event.x, y: event.y}), + }, + }); + } else { + interactor({ + type: 'wheel-plain', + payload: { + event, + location: localToCanvasCoordinates({x: event.x, y: event.y}), + }, + }); + } + + return false; + }; + + document.addEventListener('mouseup', onDocumentMouseUp); + + canvas.addEventListener('wheel', onCanvasWheel); + canvas.addEventListener('mousedown', onCanvasMouseDown); + canvas.addEventListener('mousemove', onCanvasMouseMove); + + return () => { + document.removeEventListener('mouseup', onDocumentMouseUp); + + canvas.removeEventListener('wheel', onCanvasWheel); + canvas.removeEventListener('mousedown', onCanvasMouseDown); + canvas.removeEventListener('mousemove', onCanvasMouseMove); + }; + }, [canvasRef, interactor]); +} diff --git a/src/util/useInteractiveEvents.js b/src/util/useInteractiveEvents.js deleted file mode 100644 index e4f2c5e148bfa..0000000000000 --- a/src/util/useInteractiveEvents.js +++ /dev/null @@ -1,132 +0,0 @@ -// @flow - -import {useEffect, useRef, useState} from 'react'; -import {durationToWidth, timestampToPosition} from './usePanAndZoom'; -import {EVENT_SIZE} from '../constants'; - -function doesEventIntersectPosition(position, state, event) { - const {duration, timestamp} = event; - - // Although it would be intuitive to search by time, - // that can result in a confusing user experience for events of 0ms duration- - // because we may choose to render these anyway. - // The best way to compare is to convert event times to pixel coordinates and compare them. - let startX = timestampToPosition(timestamp, state); - let stopX = startX + durationToWidth(duration, state); - - if (duration !== undefined) { - if (position >= startX && position <= stopX) { - return true; - } - } else { - startX -= EVENT_SIZE / 2; - stopX = startX + EVENT_SIZE; - - if (position >= startX && position <= stopX) { - return true; - } - } - - return false; -} - -export default function useInteractiveEvents({ - canvasHeight, - canvasRef, - canvasWidth, - eventQueue, - state, -}) { - const { - canvasMouseX, - canvasMouseY, - fixedColumnWidth, - fixedHeaderHeight, - } = state; - - let hoveredEvent = null; - - const [selectedEvent, setSelectedEvent] = useState(null); - - const lastResultRef = useRef({ - eventQueue, - hoveredEvent, - selectedEvent, - }); - - useEffect(() => { - lastResultRef.current = { - eventQueue, - hoveredEvent, - selectedEvent, - }; - }); - - useEffect(() => { - const onClick = () => { - setSelectedEvent( - lastResultRef.current.hoveredEvent === - lastResultRef.current.selectedEvent - ? null - : lastResultRef.current.hoveredEvent, - ); - }; - const canvas = canvasRef.current; - canvas.addEventListener('click', onClick); - return () => { - canvas.removeEventListener('click', onClick); - }; - }, [canvasRef]); - - if (eventQueue == null) { - return [null, selectedEvent]; - } - - // Ignore mouse events that happen outside of the canvas. - if ( - canvasMouseX >= fixedColumnWidth && - canvasMouseX < canvasWidth && - canvasMouseY >= fixedHeaderHeight && - canvasMouseY < canvasHeight - ) { - // Small mouse movements won't change the hovered event, - // So always start by checking the last hovered event to see if we can avoid doing more work. - const lastEvents = lastResultRef.current.eventQueue; - const lastHoveredEvent = lastResultRef.current.hoveredEvent; - - if (lastHoveredEvent !== null && lastEvents === eventQueue) { - if (doesEventIntersectPosition(canvasMouseX, state, lastHoveredEvent)) { - hoveredEvent = lastHoveredEvent; - return [hoveredEvent, selectedEvent]; - } - } - - // TODO I think we coulsed use a binary search if we just looked at start times only! - // - // Since event data is sorted, it would be nice to use a binary search for faster comparison. - // A simple binary search would not work here though, because of overlapping intervals. - // For example, imagine an event sequence A-E, with overlapping events B and C, as shown below. - // - // AAAA BBBBBBBBBBBB DDD EE - // CCC - // (X) - // - // Given the cursor position X, it should match event B- - // but if it happens to be compared to C first, it would next be compared to D, - // and would ultimately fail to match any results. - // - // Eventually we should create a data structure like an interval tree while pre-processing, - // so that we could more efficiently search it. - // For now though we'll just do a brute force search since this is just a prototype. :) - - for (let i = 0; i < eventQueue.length; i++) { - const event = eventQueue[i]; - if (doesEventIntersectPosition(canvasMouseX, state, event)) { - hoveredEvent = event; - return [hoveredEvent, selectedEvent]; - } - } - } - - return [hoveredEvent, selectedEvent]; -} diff --git a/src/util/usePanAndZoom.js b/src/util/usePanAndZoom.js deleted file mode 100644 index c14df88739114..0000000000000 --- a/src/util/usePanAndZoom.js +++ /dev/null @@ -1,403 +0,0 @@ -// @flow - -import {useEffect, useReducer} from 'react'; -import {getCanvasMousePos} from '../canvas/canvasUtils'; -import { - BAR_HORIZONTAL_SPACING, - MAX_ZOOM_LEVEL, - MIN_BAR_WIDTH, - MIN_ZOOM_LEVEL, - MOVE_WHEEL_DELTA_THRESHOLD, - ZOOM_WHEEL_DELTA_THRESHOLD, -} from '../canvas/constants'; - -export type PanAndZoomState = {| - canvasHeight: number, - canvasWidth: number, - canvasMouseX: number, - canvasMouseY: number, - fixedColumnWidth: number, - fixedHeaderHeight: number, - isDragging: boolean, - minZoomLevel: number, - offsetX: number, - offsetY: number, - unscaledContentHeight: number, - unscaledContentWidth: number, - zoomLevel: number, - zoomTo: null | ((startTime: number, endTime: number) => void), -|}; - -const initialState: PanAndZoomState = { - canvasHeight: 0, - canvasWidth: 0, - canvasMouseX: 0, - canvasMouseY: 0, - fixedColumnWidth: 0, - fixedHeaderHeight: 0, - isDragging: false, - minZoomLevel: 1, - offsetX: 0, - offsetY: 0, - unscaledContentHeight: 0, - unscaledContentWidth: 0, - zoomLevel: 1, - zoomTo: null, -}; - -// TODO Account for fixed label width -export function positionToTimestamp( - position: number, - state: $ReadOnly, -) { - return (position - state.fixedColumnWidth + state.offsetX) / state.zoomLevel; -} - -// TODO Account for fixed label width -export function timestampToPosition( - timestamp: number, - state: $ReadOnly, -) { - return timestamp * state.zoomLevel + state.fixedColumnWidth - state.offsetX; -} - -export function durationToWidth( - duration: number, - state: $ReadOnly, -) { - return Math.max( - duration * state.zoomLevel - BAR_HORIZONTAL_SPACING, - MIN_BAR_WIDTH, - ); -} - -function getMaxOffsetX(state: $ReadOnly) { - return ( - state.unscaledContentWidth * state.zoomLevel - - state.canvasWidth + - state.fixedColumnWidth - ); -} - -function getMaxOffsetY(state: $ReadOnly) { - return ( - state.unscaledContentHeight - state.canvasHeight + state.fixedHeaderHeight - ); -} - -type InitializeAction = {| - type: 'initialize', - payload: $Shape, -|}; -type MouseDownAction = {| - type: 'mouse-down', -|}; -type MouseMoveAction = {| - type: 'mouse-move', - payload: {| - canvas: HTMLCanvasElement, - event: MouseEvent, - |}, -|}; -type MouseUpAction = {| - type: 'mouse-up', -|}; -type WheelAction = {| - type: 'wheel', - payload: {| - canvas: HTMLCanvasElement, - event: WheelEvent, - |}, -|}; -type ZoomToAction = {| - type: 'zoom-to', - payload: {| - startTime: number, - stopTime: number, - |}, -|}; - -function reducer( - state: PanAndZoomState, - action: - | InitializeAction - | MouseDownAction - | MouseMoveAction - | MouseUpAction - | WheelAction - | ZoomToAction, -): PanAndZoomState { - switch (action.type) { - case 'initialize': { - const {payload} = action; - return ({ - ...state, - canvasHeight: payload.canvasHeight, - canvasWidth: payload.canvasWidth, - fixedColumnWidth: payload.fixedColumnWidth, - fixedHeaderHeight: payload.fixedHeaderHeight, - minZoomLevel: payload.minZoomLevel, - unscaledContentHeight: payload.unscaledContentHeight, - unscaledContentWidth: payload.unscaledContentWidth, - zoomLevel: payload.zoomLevel, - offsetX: clamp(0, getMaxOffsetX(state), state.offsetX), - offsetY: clamp(0, getMaxOffsetY(state), state.offsetY), - }: PanAndZoomState); - } - case 'mouse-down': { - return { - ...state, - isDragging: true, - }; - } - case 'mouse-move': { - const {payload} = action; - const {canvasMouseX, canvasMouseY} = getCanvasMousePos( - payload.canvas, - payload.event, - ); - - if (state.isDragging) { - return { - ...state, - canvasMouseX, - canvasMouseY, - offsetX: clamp( - 0, - getMaxOffsetX(state), - state.offsetX - payload.event.movementX, - ), - offsetY: clamp( - 0, - getMaxOffsetY(state), - state.offsetY + payload.event.movementY, - ), - }; - } else { - return { - ...state, - canvasMouseX, - canvasMouseY, - }; - } - } - case 'mouse-up': { - return { - ...state, - isDragging: false, - }; - } - case 'wheel': { - const {payload} = action; - const {canvas, event} = payload; - const {deltaX, deltaY} = event; - const {minZoomLevel, offsetX, offsetY, zoomLevel} = state; - - const absDeltaX = Math.abs(deltaX); - const absDeltaY = Math.abs(deltaY); - - if (absDeltaX > absDeltaY) { - if (absDeltaX > MOVE_WHEEL_DELTA_THRESHOLD) { - return { - ...state, - offsetX: clamp(0, getMaxOffsetX(state), offsetX + deltaX), - }; - } - } else { - if (event.shiftKey || event.ctrlKey || event.metaKey) { - if (absDeltaY > ZOOM_WHEEL_DELTA_THRESHOLD) { - const {canvasMouseX} = getCanvasMousePos(canvas, event); - - const nextState: PanAndZoomState = { - ...state, - zoomLevel: clamp( - minZoomLevel, - MAX_ZOOM_LEVEL, - zoomLevel * (1 + 0.005 * -deltaY), - ), - }; - - // Determine what point in time the mouse is currently centered over, - // and adjust the offset so that point stays centered after zooming. - const timestampAtCurrentZoomLevel = positionToTimestamp( - canvasMouseX, - state, - ); - const positionAtNewZoom = timestampToPosition( - timestampAtCurrentZoomLevel, - nextState, - ); - - nextState.offsetX = clamp( - 0, - getMaxOffsetX(nextState), - offsetX + positionAtNewZoom - canvasMouseX, - ); - - if (nextState.zoomLevel !== zoomLevel) { - return nextState; - } - } - } else { - if (absDeltaY > MOVE_WHEEL_DELTA_THRESHOLD) { - return { - ...state, - offsetY: clamp(0, getMaxOffsetY(state), offsetY + deltaY), - }; - } - } - } - break; - } - case 'zoom-to': { - const {payload} = action; - const {startTime, stopTime} = payload; - const {canvasWidth, fixedColumnWidth} = state; - - const availableWidth = canvasWidth - fixedColumnWidth; - const newZoomLevel = availableWidth / (stopTime - startTime); - - return { - ...state, - offsetX: newZoomLevel * startTime, - zoomLevel: newZoomLevel, - }; - } - default: - throw Error(`Unexpected type "${action.type}"`); - } - - return state; -} - -function clamp(min: number, max: number, value: number): number { - if (Number.isNaN(min) || Number.isNaN(max) || Number.isNaN(value)) { - throw new Error( - `Clamp was called with NaN. Args: min: ${min}, max: ${max}, value: ${value}.`, - ); - } - return Math.max(min, Math.min(max, value)); -} - -type Props = {| - canvasRef: {|current: HTMLCanvasElement | null|}, - canvasHeight: number, - canvasWidth: number, - fixedColumnWidth: number, - fixedHeaderHeight: number, - unscaledContentWidth: number, - unscaledContentHeight: number, -|}; - -// Inspired by https://github.com/jsdf/flamechart -export default function usePanAndZoom({ - canvasRef, - canvasHeight, - canvasWidth, - fixedColumnWidth, - fixedHeaderHeight, - unscaledContentWidth, - unscaledContentHeight, -}: Props) { - const [state, dispatch] = useReducer(reducer, { - ...initialState, - zoomTo: (startTime: number, stopTime: number) => - dispatch({ - type: 'zoom-to', - payload: { - startTime, - stopTime, - }, - }), - }); - - // TODO This effect should run any time width or unscaledContentWidth changes - useEffect(() => { - const width = canvasWidth; - - const initialZoomLevel = clamp( - MIN_ZOOM_LEVEL, - MAX_ZOOM_LEVEL, - (width - fixedColumnWidth) / unscaledContentWidth, - ); - - dispatch({ - type: 'initialize', - payload: { - canvasHeight, - canvasWidth, - fixedColumnWidth, - fixedHeaderHeight, - minZoomLevel: initialZoomLevel, - unscaledContentHeight, - unscaledContentWidth, - zoomLevel: initialZoomLevel, - }, - }); - }, [ - canvasHeight, - canvasWidth, - fixedHeaderHeight, - fixedColumnWidth, - unscaledContentHeight, - unscaledContentWidth, - ]); - - useEffect(() => { - const canvas = canvasRef.current; - - if (!(canvas instanceof HTMLCanvasElement)) { - console.error('canvas is not a HTMLCanvasElement!', canvas); - return; - } - - const onCanvasMouseDown: MouseEventHandler = event => { - dispatch({type: 'mouse-down'}); - }; - - const onCanvasMouseMove: MouseEventHandler = event => { - dispatch({ - type: 'mouse-move', - payload: { - canvas, - event, - }, - }); - }; - - const onDocumentMouseUp: MouseEventHandler = event => { - dispatch({type: 'mouse-up'}); - }; - - const onCanvasWheel: WheelEventHandler = event => { - event.preventDefault(); - event.stopPropagation(); - - dispatch({ - type: 'wheel', - payload: { - canvas, - event, - }, - }); - - return false; - }; - - document.addEventListener('mouseup', onDocumentMouseUp); - - canvas.addEventListener('wheel', onCanvasWheel); - canvas.addEventListener('mousedown', onCanvasMouseDown); - canvas.addEventListener('mousemove', onCanvasMouseMove); - - return () => { - document.removeEventListener('mouseup', onDocumentMouseUp); - - canvas.removeEventListener('wheel', onCanvasWheel); - canvas.removeEventListener('mousedown', onCanvasMouseDown); - canvas.removeEventListener('mousemove', onCanvasMouseMove); - }; - }, [canvasRef]); - - return state; -} From 963f62f69dc0bf84deb781312c3634b74d2f7c88 Mon Sep 17 00:00:00 2001 From: Kartik Choudhary Date: Tue, 28 Jul 2020 05:26:47 +0000 Subject: [PATCH 051/116] Add key mappings and legend to import page (#88) * Add controls and legend on landing, move assets into folder * Remove spinner css * Update controls --- .parcelrc | 3 ++- src/EventTooltip.css | 2 +- src/ImportPage.css | 35 ++++++++++++++++++++++++--------- src/ImportPage.js | 26 ++++++++++++++++++++++-- src/{ => assets}/logo.svg | 0 src/assets/profilerBrowser.png | Bin 0 -> 77466 bytes src/{ => assets}/reactlogo.svg | 0 7 files changed, 53 insertions(+), 13 deletions(-) rename src/{ => assets}/logo.svg (100%) create mode 100644 src/assets/profilerBrowser.png rename src/{ => assets}/reactlogo.svg (100%) diff --git a/.parcelrc b/.parcelrc index 3632b45b34fa7..41b6f1930c9a1 100644 --- a/.parcelrc +++ b/.parcelrc @@ -4,6 +4,7 @@ "*.{json,json5}": [ "@parcel/transformer-raw" ], - "*.svg": ["@parcel/transformer-raw"] + "*.svg": ["@parcel/transformer-raw"], + "*.png": ["@parcel/transformer-raw"] } } diff --git a/src/EventTooltip.css b/src/EventTooltip.css index 2403d6d73d388..f60e83208cc55 100644 --- a/src/EventTooltip.css +++ b/src/EventTooltip.css @@ -30,7 +30,7 @@ text-align: right; } -.DetailsGridURL{ +.DetailsGridURL { overflow: hidden; } diff --git a/src/ImportPage.css b/src/ImportPage.css index dbe9df8885c09..bf55d3fa7d7db 100644 --- a/src/ImportPage.css +++ b/src/ImportPage.css @@ -8,7 +8,7 @@ flex-wrap: wrap; align-items: center; justify-content: center; - font-size: calc(10px + 2vmin); + font-size: calc(10px + 1.5vmin); min-height: 100vh; } @@ -21,16 +21,32 @@ transition: 0.2s; } -/* React logo Spinner */ -.reactlogo { - height: 40vmin; - pointer-events: none; +kbd { + display: inline-block; + padding: 0 0.5em; + border: 1px solid #d7dfe4; + margin: 0 0.2em; + background-color: #f6f6f6; + border-radius: 0.2em; +} + +/* Landing Graphic */ +.browserScreenshot { + width: 35rem; + max-width: inherit; + align-self: center; + justify-content: center; + border: 1px solid #d7dfe4; + border-radius: 0.4em; + box-shadow: 0 2px 4px #ddd; } -@media (prefers-reduced-motion: no-preference) { - .reactlogo { - animation: spin infinite 20s linear; - } +.legendKey { + font-size: calc(8px + 1.5vmin); +} + +.legendKey > svg { + padding-left: 2rem; } @keyframes spin { @@ -56,6 +72,7 @@ hr { } .column { + padding: 1rem; display: flex; flex-direction: column; flex-basis: 100%; diff --git a/src/ImportPage.js b/src/ImportPage.js index d6367da7b27d5..8c10952923193 100644 --- a/src/ImportPage.js +++ b/src/ImportPage.js @@ -4,7 +4,7 @@ import type {TimelineEvent} from '@elg/speedscope'; import type {FlamechartData, ReactProfilerData} from './types'; import React, {useEffect, useCallback, useRef} from 'react'; -import logo from './reactlogo.svg'; +import profilerBrowser from './assets/profilerBrowser.png'; import style from './ImportPage.css'; import preprocessData from './util/preprocessData'; @@ -63,7 +63,11 @@ export default function ImportPage({onDataImported}: Props) {
- logo + logo

React Concurrent Mode Profiler

@@ -76,6 +80,24 @@ export default function ImportPage({onDataImported}: Props) { performance profile {' '} from Chrome Devtools. +
+ To zoom, scroll while holding down Ctrl or Shift +

+ + + + State Update Scheduled +
+ + + + State Update Scheduled +
+ + + + Suspended +

diff --git a/src/logo.svg b/src/assets/logo.svg similarity index 100% rename from src/logo.svg rename to src/assets/logo.svg diff --git a/src/assets/profilerBrowser.png b/src/assets/profilerBrowser.png new file mode 100644 index 0000000000000000000000000000000000000000..b0282be2f68289ae83da05816100e26a1b7b35cf GIT binary patch literal 77466 zcmce;c|4oVzwns8%x5y!eBRgf;(@{4 zQz!UO004kf_wU^?1^^DN0ssdKjvd**vbg8-006iExPRxCsek6uM1bFUW$Xe?__UtP z<@|o*;>E>9=606q_DHr@+sv>ZDJxY|Z9DB8sm{-h3K;@jDXM(ceTBDq;ntnYiQM;J zb6;`1M>15>vzEJLe+%FbI6TE7bB4wp+?NCZsP=dT{K|~L5AXM2KfMGTQ2Uj+^e2Gx zXQuhs>E=T}GuICOKP$51N`3ETK%+USyv3XHPRt{*U#A}xncvlGJ$tuK@MmWLD{mNu zn!8(siz8}Xn?nl-s4@2f3l15kZ*6N%N9)aKa!~;Js zJ>(m=0_-h53COo`4~oP2O8vXb!uEqThPF>2!+ecx;ST@dZfz*N#nxRR(5IKoV(A~< zNb3yo^$Thnk17Hi(m)Y&{|NLW6At;zTKumIb%GP4 zXRp*CRim@)$*r#(Jp^ZO)W(Y-&b{*W0L?1Y#xFNSc}E~GB6j?>JA!2W{QbH87#AQl zHO4n`>s+CwzOUQ~{b20yWf{!Su9r`_uXY0#i zg(jWg?!H-dEtRkLH&@TDt~y#p3i6I zMnQJ4P3J~aVbBgdxpDj%u0DGuU23a1B;Us(-+rgW|J^4(dzF(@Eta5unx?L1V@g5( z=G<*E>y~*K*pBt>9-UQJY2nLO)ltJQPNnMEsx3|iwHGTcjvDo0hEZldgOwiiZy^Qk zjM1vGb0y)vl^iP8)iH~mCCnG3s_GNgiJ$@w^INj<5d@&E-3F}4zvxwy?pET_xl8I- zg|Y>{m;+NAZO&JbxBb0ek-sVo5FnVad5?3Oo7cX3OcbyBp05+4G6WRvjVN0y7@>J@ z>D4bhEyT~;46OU|vw6UM<7}m^m>wg=ZuvnbXgp^_L1ZWl$M6^2sxgnVkqJLR-JA_6 z5IbtFHe{XIO4@77*PaS}#p=_aHsOdh&s9xTov@3I4iJcj#@zkKFkOp;oM0 zp_WXe=pM23%wrQM5*z#g}uBpP!;Yd;WG5q#c>?nF`Yl$zN zPA;XgqS&ZtN-BL|kwzyj3P=<4=R*uNvsl(mZ})T=J0Ihh#LF)6N|N_>_{f^f*v-vI z`HpCZ)&P1|^oR`N>8sUR^fK3|YH6>`r-~@tEXz@FRg_z8;M zOgC&h_i?zKKtocErx^Ad-A61XEU4}!gHn>f2~#i4VKox*84mYWL2EZ)?I_c3O;!4n zC%+sW8Yk{e5CUpR-8c*r+9PhPP%*}I+Ym|M z%9K#7*~f|)aBdUMWoYD;0_F0Pq=P&H{H_l13PQFiS))wfO2yg!FH z^{g^GDU_M>)ek+k^7Vum%BHf&#va#0cu+~v&W{VPyg)I;3kaG|T>s)Wor+q5-Vi8X zAHY|5H(9r0 zjcrTx3XE~x{EW!Gl9DeMrA@cWj(J7~~!5{fIQSqyz&o(i#25re;^=U(r z?jB=LlDQ%PTU%kDYALnxD3ev+S;|Vdnvc-#3*F1y>ZUFdw59D?DZFX+d!PSzG;^Adv zmS%j*`~yRzaOKH%@~EGH;@iNAj8uAgNQ%&zv+NYlP#eu*Pp?5pBI`_8?zRsduJGRe zz@)0=8B`UsegSezJ0Q z@Af!G`gRuXifq+d9I$qj0li=9vRYfFp;N@-zVH>@)=xe{v8x((?9C5Xi<41XjIzOG zcm1$vW`3&$LO%yidM%i8$HnYO@(f(!u{5>Y+lUO;3cS4XAprHRl<>r7u<)*{^Ox(| zEB&cH#um+wlRJIexuTXQDL(g3L68MO8Ub&7+RvC!VM_W{Zs@Y|Y>;lKnsfc+7^{OH zIWrodi!kxR1V2F!)Fp`bSZ%x5@_x2D?F_xCFrL}6NJ*htHrwI5!IRLBAt&DVI`JatNiKByLaUZ)~sEhO$ESOU_J&Z#C`qsT-trZfRMWLms-{o~=RG$9={G zw%CS#Up(z#t7IXS=N{s}v8D7F+S%#Sb$7`g8*l`h5bQY!Y1tOkEF@D-rO-wTjH}xG zc5p-IqIOwW7x@_VPj>25v(T#>ZrNuj56WiB0edQ~ty!DR?I9Kzdcf;(!uVY?k-*`^ z(9}nj?{P-nMl#uzeHMDLRps*KW?X2aKPF$>eZy8#d-ItzsQfLYiWTSJif~J_C<-I1 zS}cOIG}KahoyDc#KJ`*Q!~FY=?g`avCRW;&t@;U2UO05F9eS_Y-_lDbt)?f=U)zdk6B?=rWi$k}<_BCG z;vC@@Rz0^&nDud@93wx7Eel>ohMTWC(x5A>K=v08;o zE~s#<8Pa&7pWP>)cK>mlNb6s%pPqcaG6tm@1WuunJEM*-SxVY`xB9W9Q*9Q{@Jbb0 z6h?kZ#ioW9q#^Por#Ni%jxT5b9p4#c-YFc$Y(svn8&_IsT~c4*1cQgJKcLSU z=ApB_69+6|4e(LSQ=;v*swCM(z*cQ3aE%%!*cqXYW|$yO7*Jjt+5(5)Iwekyc)fEM zIOl?zRXmUiOv(*8XvV0BX~7i@;6{mJ&pxe`w?TupX_MpmIp0zg7gfxwYSG2%#m8?Y zOAO`cI<(nT7X~PjO1?b84JvYmtFQCXu`l74aowV-V+d>(B66(GP3{IV(bC;)D0^JY zOcOIx=51>|bH)bQ0wO4Z7inVmOIeXa#s1(swbX*C#u@ zDKBcYhC*no-JiV)S-W$&rSY#E%Sy0+IXW~kdu>A5BlCP3Ez@8-&uJ3@?okyZ>+5NT zmu4rmH9mhxl=)zQIP-}A`IGC5lc$8&44@%+gs$v1dTS*#MdRo8VM%yzZT~MTe)EWn z#rmC`eOpvIQEHi>+Z0dX-W_|bzpHO+5K?U06PkN> zZYImNt(*U%%g8(R4Y%AQnHxoG)2SF+GG!F6(B-IFmTI2JxG0#Q@aKpN-6oA=J%}Di z_hJS+CXOtJM4VXtXi@Y8j{+ZYjjS#|zW?~V(7#7_&nNAcuuq!9r`+<#yq)tCed)^+Iy5jPOswBAIE7}P9{QHBoN^HkWgc?wO8xy?)Mtt;!w|IHW0Au(V z4oQtSzid+WcbxlA7A~LlqT$6$F{4Z0%}8ZVcCI@&sd524ofYq-Y`b<|rG!eU+Z%+dEZsRqdOyT`b{h~ z!^Abu*F*M6ag?*~u0G-3XnGf&u% zC%;vA-{|fe%172%-nPGysqV{A%G*E-Lu9jvaC?Ur6AVQutYF{{Bci5_U2mf)pda{1 z30u}Sk1D5!C2u$?CWmY#Zwi+Pt@`kFb1vPn*g<4Rmtx!YBGk#kAtKE7P)X*l7$4p` z^pr1$iPg4-!eL8={H2BRoq92dh|f+SUxPXPrL*MmVCeP5M719N(8Q?Giz0~? z?)6&yicjMBct#Vg>LIBu+os-AouDwa)HXM0M%Oek6=;kMCEdkXg;U)9Nkhgxg zR(s%vA}wy;S23N$kCuW{$actWrZ#%7i#G8`rP(#sE<3p+qBMVlS3$gKG39WjiQ8Ik za%)YW&a2No)e|1yysfS_?@O+F@3rNV?yCRljK zj*{lG$29~>)%9PcY^iV9t8*|AaWboyEL&I?32z@IC|bzwmL`M)R;>B`Z2S)F1Q->c zdW~@+juZY8Eq51{rCYx7y+h>m8)K3+skuG4~PZyFW%G|I{IM;7glvz8- z*!OJJY8yP|uw05$!I=j!Pzx3$PQRS_p(fj>3FYmkZ3lOhNxC@Dju{I-1uo0jS?c%X zE4LGx%(8W_)xK>R41UJ2ydB^UO7}ZHj;~N7=!jWj>!JL08vvnShk6Z=5O42p=t01E zOzEY`tnR}UtXpl30uM3lt(}hh{)w#{)F3RRQu}O5POYoi!m6S;-J+1ul(zfBUqog4 z0Dvk1r2o+nE(fgm;DR%=kdJW?)x^sN_g0{CwRq-SEP^^-uI!%(Lj)TZK@X~nO_K~l zQb>y!dEQ1V=10Q8&AQojLwhsH3=3I&Mdp5=R(l^w;;fvkiuzJFJ}hl%A)C%i1l=6i zOyvpy%Y9$MQVg7VQ7ML!b0+8=zO?oJeAfeju(k4R+Aw>e6A2~Hn7)@FydV)0fDVdp zgwtvV`03LAw!(^5!bf{tt6nnTcR$`0A`}2L@W-e2doN>kO(@f>lLyyxV4f!)yaNZP zNF>TuD6zYNyFf;E%iK4>i&xFK0fGH}f^D;2fLD*&Dc!bewl zn9?POsP*}<`oJhkikVj_gIQR{u^R}vPL$mru*HSRO0!pV?oUcpDC*=@{X9ZVaj~w3 zW6W~KfnY(a$Pyz;LvgX$szHuO*ipbk7h?b-AhJyyFHi?HO}vYuSXqJpBsFfFv3w`w zT=b$!i%@*r05lXQtqH>aIJR|Q*J}Eb?dtwyVU7Ob;YC$=A=#>1TySfJQuHXTqmzHg z4YSmx@MZEwwhC$8OnzB`t0U^v>6R!k&UJtxW!SCI3=` z!ak#z&EVf}n%77%X41*vtIkklqmx>;EoZGb<%MC(JaMFbSvZvWQONMi0_NQ9?*{-i zZBS$`bC5H&c9F6l8u4$St~0rint39d@$nphX4mH{rc*1A#_6M5%ir8nDu}LMde3wm z+IPg3%VeTG)q1Z-I%REbmTTPAJ?QSJ=REYwMV~8xW>w0G#GLL)iF%V;UQi>h=v1Q% z2lgw09RkLS1sf7BHlkgEb%%};o*n(^_YV&r+n@gX>Fj}ne;@Sgg#EoDgq`^!IMDYi zT2nUAFZWdBup^W0SC!~|KuEd8)x*Cl_$JfhoqjhG5v-VT{jXmuN|<0uR9_JFr+4kA z5xadK_D*#Gf&TRP$Y4DEm4g9|ljOFugYXkK~58~7`ya}iw} zuPxNZ*@lJ3;iH_>;B(J{x`k5O8hOjtiE4mRpjtL zrrOs#>&Fj^|1f6w{M`B9LALr%OMqsU{yD9`V-y^Ex4&bgF8x;Ze%;A%zke(y@LP@l zT^MdwG4b!%)CdI1OFw-Ovp*L+ZWjqQxSup^B`Z5D`hu0UWdMNM7u?NgGuY3j-M(MG z>BpB+NLILx`|GEw$M2n(B32t68x-9y$HCqiky-3x8f1-pVl{U(a$G7=AaIP)jDy^b z)LD;AN_N}W_suZm`lL9*Kx}j0&>q0FM8dj?Ri#yM4Po+Weuuj*P^fpdft&b>&HDuLF#Kg{ zmpm|6@{YB(rFXfiw(Ne#qPUyEs|NcfYu?J+S)^YbKj^a%{bK16eP*7t89t)ES6bSA z<)1*Z@<4XKMGy zz!~;a=6?Dw7K#7lNzcX$-v4rMK)s~&CG+8}qn1Y}HM;ZjpXQET-6^5$a*F5*kE(2H z2*UjIzc%_AkgqLk`ZW+D8H(tAw-?cLaX+6*P3I`FZRI~W!XLFqE&Cy=(FLaF5}Wwzo#YD?jVY{wbN6} zf}jok*1mOb#gEuhbLNwCRmHg+jy9NnpX-6oW6F&zq^fp(QQx!XHPfz=>N92z0;UvC zI{YZ!x~2-Xb5~nuAU_oBB#>(RIY28V9 zjH9iOJ6d9v4WM`_el^&uF((pNP>iFUP0RP;u&nu4G1uYW8 zpPj6#jphbna-Kzpo}S6GECKCWi0?7k$sgf6vO@W_m@OmZoE%&6Kr~k}FCs4Qk{sKr z<-F!S02RIzmDf?2O`d+iwjejEQJe7a$JT=%g*oTePxR8-$JLKgnG=G@2iEDn%jIXZ2~RfFlvn&>QFkvcxeIqG90mlZS9h(NnvJb?>r8yF zxM#UPw?C~@xZPC|>lB&B7i6ae>B-~btO`<>P;@c4PPE{xe3zWIFjnM;VtC_TmO#f@ z`p?yi)hIk}n32HT=vPsF4W{kbr>jj}B;LJt9_h6ZytC-+4GvEWVVXrHV#}83xp2Du zm|{MzT~Lu{34Su97F zj_95(&EzmZ@QKWC9nR;7u83`nbb#{X(-|*)t;Ob+*5!vgXztLXv;FC%1~PxS6+LLM zyUKT4P2FUz;3alSJ>#jbMU+B3`Xq6%efPe@CBeOW2}f_@eKV)6$Gwe>_Rgm+Tg>&K zMUDupdowgP*GA0rF@omtB?hl$Q<2^eN;UuTJ3ci-Xd>3Ztz4R7(yMK3()bmg9=)ZZ zGGvEp^+cV1WHl_)8ou&4!`yQsQG@$a3!G6+Q_X5{GwE0wo*oF8v%1t{+NE7sVl5fU zogaV%;f&!f?0juK2G+FTdKB-=n#SR*^SR4@6E}g*=BbgfPLcx zBkKU^nX>&~pJmkI1Mzx39!MXyh&u&n^=fUNytjE!1E6uG93Nz0b=7`vgS@MpUCB)e zf8u;MzoMniq>dP{Lk*g#)|AW^ugXCgJh!;-r93xaHJYgJCYW!D8VbBZ!g>j4R>K~w zT~aPAd~*`YCY*jE&`AL%P(rwOilXak63Y(eeU{ z2&gLS!;vbwi7G?a2|lLv-8uthu0EG&^_sz42{5$UMmo@XF%K7FDy|UcZ5>(p755^M zW`G1C7w5D_yX-p_);Sj>s6Om-g?~PP#QO5!;w8|cDn0B7{^nwptN6T&6bX+>Wz^z3 z(2N1kC5#qU$x8x*WUB;83zmi#n~h0kZ9A31o-}^%fy3zUQx+AAOZazMC3=MVI+2i8 z?}1c?!JLg~Dkn;PLI|5vIOd~%?{4yd-CY09q$J##;|oq+5~3tG^@e$@S{S7NajV2b zV!g&zQq>^Hu-dAt$)>32{W^mSxZ>2gz9D%r!tSr;qOaQ-B<)DW&VGY@{f+wt0iF@- z6E>tHC{9Vx-Kv;0bI(_Z!LJ8`$4hpfWTgNL)M)A4GCT!l*T9WW0tOf7j7QgWwaGl9 z+KaDi8a~B6=H-**N{KV4Q~+mO(^P@6ZWq&O*+a_c2OwvJP;m%Ed<8EbAa7)LlOV6z z?)WYmQf!(~G*nWuBqd*$DyeEh@_?(`F^fSTtaun{>jBl0(OwQkTIX@R?YE}qbhWvX z1d}?c3q_6Burd-;=S$IsvI2$J*A*aX+elNI)OM5zHnXn$-cA);C0H<{P{+G)_;6jH zA7JE(MC^3&yRBH!R;NV#QwJ{6R$oFG&8ALr!D_HBrlfCwO&Iv*lF&XEHMQc;Q}rZW zUW+juQd-en8C>4K*!sGY)MTcZ2CE3QWdxa=a#C&$G%6lWvyt+Wb}kfiNReqqiawdo z$8{Guzdu3UdVie0cJl+-uq;{3aK$OG*8EB6BDV}VSxCiqOuG-MookMKhv=45-ybq< zWn6^ZvbuqN5g2f`vhvRchvHAb1oG^&hr$XlKT4p&WPO6Oj4irNG*EIajxG;1f1I&;QMP6|F7x|Mo~TzDhd zwp(8L3%7vW*hZd8gdeohatk}O2t@{bkq@{Ds#`Er2q_GEmrNi@gPKmJ>p$&Tz?dX| zxn5T3KNu)&L$C_1AN*KMSSsWK3IP>H@!TXoEjA56tO)_N8A#p=JSQJ?24rQ0;7O+f zH98maHF@~9nXa1a<4q4CAgjh>ouX+4hK@yCiZ3rGV05C##Z8{uxOQ`+Qq}6`Z_M4M zmLxbcj^;s{1eKBJ@6`DqzoXEjl3gW!3NG1Iy279!g^ve)hzT-Rt1jS9$uO-gO({5n z>tMxGagRzGPa3Yb5WnV522Q^0_TIK691p#&Jd7wccThPKgyL1xy`%+nhsut{f5qOMB!jUZYk}(Vifc@O@pV z%N^4|og1Gn`BZNg&y6O;mxuCeBww;5%sr#3hSdy6h`C2PN&IQu>1CoJa85B$W?12x zl3Bc&jF0?ZV?u|P`X}a7Zyr51%hkJ8uc{bNa>hRD|hkA{8;tS{1 zGi7wx38T!p4rAiIa`O7;91i@$L{F@Im~i7V*bEj6hjkE-eJ|;n>Fot!kj4PgGSSgd zZtF(RMDsO91VyY!)u(zgb89!Qy@(DUdHL)n^Pu0fcUgI;3{%iCxXBnsB*d0JASp9O z=2x>5b>7_&rdN9j;{)(@!oDmS1br1YI4q+sy%uf`S>ShZj|jZHdYsr>7PWpkTP^Lo zMpUHXi~uS0`NGu9s)&JmN^9-xXIG|IvX^hqx(}aEJHNZBEkGw$yGru}A8)?!v^+S& zVRn+ZW}SO_WCb@7vQxx%V7!CkW>%eP-HL3YyU;CC%IrT#0T3mL;JxrD zUB7wKnfig-7ZPxdh7xZDMUyV0reqszsbrhK?_qI;=UwxVq{FFnITB9O&4{BgRU1 zN$J|=?w!R4LQ)k3YhQjjEF=n9PMhN#o3P zZssRoy;7)(YR&`)>GQ%I({qD)G+mSI^05xrCO#R`+nXmlESrmk*x)?fG#@DYW*G3y zWXQ|)+8>blR^3^Li4|A&3q1EEIC$K5OVs97Lc*UyEmkHANmW&2_GpI?T$tOjgBdE$ z{NSDMgHo8v>iTr6)@O+fXPH!<7|YzPr*)PRZeAQ{SMH9Qs9StJ!Tb8i?OnUK+gr!nUM_TV3WHOvf-TpgX5s$gkfhHi)U_En_S7` z_n)uJ6niI+ml(7^SkW8Xh!K%cJyyJEwOmo>anJ!g+?X^lQzYMk6a6S@t`Ga9#Ezb$ zfAg}fchl4bbCC#c=!TSNnK+%Bv<-UmILOGWN@87SCELV}BG?NC0rShep(OYBzK}Na zJB5eLC6SV-1gru#Iys~P)inA6bS3mOw-}1xlT2_5MzDJpz$lO!oekwjO~v1~i;o^s zb!Z8|xaK)<<)ZfE;EO>-GSR2$*f6=rV?rgNI@FGWsooH5!j*j^!1|pcVVUeCbZi~O z7WYljx(P8MVDD^&m0F5rR?mQ{C#b1G7@0a{vBsvb>y4vkwL8rNM}4a(Wj?Is@oc}0 zJPK~&p^~ZhOotC?3BO9K9r~hlzFlF1*mE6m8Rcyd4J#K)F8JPxaGQH z;WTAvB>nDs#f=6NWxdj7R0;%zBlIZ|B!;PCRJ7)hU+uc9>ix;$CHgt`BFxW!FPv7p3 zj6i-nbfEovPU)ezy&ntik0!j6tAmkRfe>Cbr5t4Qf@RHXf<&X)#S)_Fr=9zy!QTu( zjzAt9uTQ~+Lg*yOt+-8m!)TwM@x^5>niUgEI(=o6V1p!S3r6zo-!>>ZL_`G>6Nt28edra+>o5+WLw<;$Lw^Kj^5PX9n1!#Zj z=5<#;V{ZXe##^@~xmb7g=-aDKjPdG;5X(!6%+l_v(KZK)bJWNL0uo!5zbvAT2#$h} zD(l~Rsn9uR>=yTcZ;5moQ1cZ!;Y|zDrNVPyM41hl2dKr;waa+yGI47ienCZk9s0zZ zEMO@b&=5QrhuiMn!CUVM`MnX7clEO-E3ObTqJlf>-E7nCLg`ITrFxt#*LfmmYYwv5 zw^WIT3w;DlY|@;Vbt@Zhl0?U9p@SVJ>Ghv_Mhca>xLV#Dm0L)1#ywT&q#sRLN?a-w zbrk;)YJUhm0CbFtEUx!@yfecx{pgm*-u8_n?hxUj6U{!`iA*2#Nt*C=_{#Pt(p+z+ zB{}AWxm1@oe7(qAQSESbi}XT^Q4PvulJD^*YIz}$u*e;-E-_{CAXl5pG(w) z7EhLvPf)ItYHAz%J|{VWwTHiPASRxuZD*BXZ)=FNCu^Tq>6?TOi-`$(ie0D6r>c(d zyHyVf+(>#xkr<$enhXW1-@_^GpU&tfZx&@1D;9KqHxl%&eJTD*D10P3D2-$L2C$%% z(pozOi25_n=B}VLSP&H+{F;nOGsH3Y6tSD?@1kQLuAvLACxY|0RjXv2;e%UGcf<@Z zL3J@5W(iYl3-`dM4rSP2C9{8Y5NPHBu|yW0^_VhdjV=t%V7p{CZFAl+aA(GfmcTC< z{2I3248H6c!7C+e?ko15f(i~*>g$_nv<`rKC6Q}a4*r;?LBk>vSMXUvOF@F@+-%|2 zq$5iz;CHMa%@ia~ip@hdA$(iRAczZ{O3}e{Mr;=v9KC@!5jB3FVwG-~<#+>eu%|{a zn|c>~UZ~2d%81j^^2A{FC>}WIYo+P~J&-sn|qwfB6YYvl^S!Tnp@Dt)#S^lPVs}&Ut3Udn&GpEvV|EQ*XseEV9Na zNXr89Ao+cKlZfq2D{XaEx5|=y25*UjE^Rt*lm2vNpnO!h+{?#(zQ4}0B)lMUxYCz$7PC?)L?SEZGygiU29Eo%(wT>hYOSm{{P-1zbdzv}WIw>bvRpXjzM-}*k%(-mg; zA{jWho9C9R*PD@%lCdG!J}xI`#J}8MRe;q?ICmDgOkeAGuJ{LCEZ6(#22I$nfm6ok zQBq>*J2H(~5M4G@UN+jh?IqeGT#f(QC+TxmPOyeoN*U-BfPKb6Q9M;hBi!JM&|T=K zX3Kmk;2TqUEtaTNDy5KCXG(7T&VTa2*u^`7HOV$+C=SyPZ@D23tjx~A2X&P;)y|_& zpa(2BJ2SNTg~kX5$b}*S;~-jtsP^l?Z$2MGtbb%KC`deAP`3}=Cpnl?ev&Vx!#oKa zfwSJVZVC{GPDm;F@f(R3(?@R0O{5*(Y+T8Ad175PRlH93B=?@0g1m-m&a0G0WXq-l zWxY-qI7J2<6?FDUD5g7EI#)s3CD_(9FaQM;*IePuVYwqfoVjw35_GvAUWu4yRr{F`K8I$$)8yIkZ}uO#BJxCM~*nGIpT72qWOD%PxP zr1<6bIT5zE3Gmn3egl2p@q=AU?-w1AprybFTXWzE$K^)Quso&?!8v?OJFSZ+va|8o z%=q*+JU1nd-%>s~zIf&A#>m_O#Y!TdwysmVYZm``(Hm$7fz7dl76LtgWEGDnNDRW? zxt$7y{?(Uv@6yRnYzQhNsIj^&;`F9v3Nn*kX?q)ArygS>tPlvPN*@)DkvV2~AXrn* z?rYm7tuC(bYH*DvVRgv&lqlisTgyYv0diVX7c=gv7r(o$ca-vBM~&K#VZ%F=o(@mR zVSlqc-pi0*@ZNvHBA^{6`-B6Avl%W-A00ewm@iX`lAK&lQ?bSn5h)R6pBx#fl4$CFJk78>0kJT7Aq< zLMqN6RQ#+>R4HE{E73_px+%*sH|+^!(93VQyWQPK_|Bic5HamD>H!Ojg&=FS8{IDm5=1BqZX(ZM;Y-Ha^#vuop z{e5JNs+U0xq0pO(P$%5%KkhazV7oSGGVUoESqlW;8&{b^@gi@kX$G&m)of8gGcT2F z{0jQfcEa>!tO;6`c{~+9DM0(`7_^3>PK2Zq>Ev(sTca2ZXA~&owlZ;Q?pu+ve6J?5 z5YHf!+9e^;)1EJY?|d9dikkJ9w3cmKr5E4gn4_69l8Te9UQI6w4R)%RVLu4=>I(|J zuB3BLnv8>m2hTz&&FCxHzya#&hyAc)bGv9l&ETSk!BSb(#D?Zn-uhVN0SKO$_7K|D zcS%Eyv{)_C=6USHWT2GTExhQ1AR^;inW2--O?{7Q946Iep~1@=GK@1bs@eRw;O0;H z5e=`OZvRXxPv8qNXm`!e$+_bDw$e>?ioZXzH?MB_Pftcw;bc8C{VaO2|4g)N<7n7a zwI)U1!)x8ryjBQ|vT~y^iNukH6=?y_!WBtZS9cf*-|G>K3IY{s%nT}PZqzK>E7x;Q zfYBa;z1e$SV9w|nU-$EjRtA@0;c?gHuH-j+8Dy7w1<$j`{INz0x*5xpO<9EwGQfMO zV*xivXvK0Lyh~H4zpYZ;-9>N$U(e~C`F4(s5tWbbis22OT4=9e)hW|S_+17wXMHrG zCpl^;9zL?m+kaexZL>CXtSuXV9sDcG4!HE6-;&&sS^nlD`Xey99fhV=+*Q{69>0{W zgs_`{69;%Q;oXb|y?{xI%+pblJ7YI9M1@sd6R<&RN?2}mWtcM=$@n22TVLPw2IR^> zeReFeaZg9wKJjClSEEcvSPhBq8$oKT=C1{w{SbXpJ%(~M_)lV2cYaY;|6_v*dHw0` z5^Xz*LPp@@CCNTF*m^#@3(FDKSf40fAQMFDxMMdVcR%AH6nRjfrGvJOtye<`cX}99 z)(Oc-OD^RX3^E95P^QO>xm6}dY z2BNc+ftRXvsRkTVvn-R5^nn$w4)=Yf9f1n|D1eqKwk!s{S$vE#=gm5?z|gfdEl@Wm^ zhSS;l!Gyf=rmA|?!s(hwLeYc1{kJ(HCpo&ZB|GRgpQZBabf9dM5yJ|UOi!d}XS68F zeS(nUE5K6<;$3FQND~RcCu30NkfV{S+m_$!<(;5;uh~WNEftC*l(u=4|2N6?hD@ zBf5#^F0?&RnwvF)b?0u7x7@V6+u8I8)gQTnS&~1BeqhPZJ`rHtl$$bN%uYyC4HCQ^ zs%Dv6ax%uG(9!*UXU`l_2c!(Tfu9q7BYT^4=d_Y)Dr+J4lbQ+qTB22UZh@U-15maK0K#@MTe;Hd~ir1Zr~ zIQF=TmCnx)toImVr<8Buy~)GmuG3W|k51ft%3hEH;%f%K!mKz?wq_5{UP#0<#-7@u z^+6Lkb~#XcLsb_R~R=!t$$eXi!Fgln{4VVksx&OI(h7dP^Ox7bmtnC#W z?kSSWbc{3^I*eNM|6|EDUpZDO1@yr3p2NI%LoL4IPbhHUyC5ii`$VNEoF8mD0ly}lxm^f(RKYCAk4Qr3OI;eBg;8%mfVe?y0^>#dHy!lN4COLw!gY}8yK(VP6L=%ZYS_~~7bm026q z;)h(2U$-wyO0#Tvq?#tCfoto1k+o2<>bw-<68^MHX?>-E7^L+QF6&0y2>zA?@pZEv zK7^~(d1aPf09#Nx&_KawKq%Tn@NBrxj-kHvpT6@hP0PVnx9wjuWQ4sYsHkVn@lcI5 zC}J{jc=JF*7HQbGTO7R<0v!$-6Q*L7mCd@iTp8|(@nSmCgj>j5v(fj2N-O6^4dc<0 ze*b3#Co7&HD}(JJY>E5o7*>3#%)YNuh2Y}zw$Yt)-nq%Yv3T_%TV5%~QYCor?P{-^!_8r6zVk4o zMX7G^Id@A24CP)}x4ii_9w*G9eo}0b1m|;jpc8I(_1Wf(MK`239byh#*4Uy zf%!9uNO&K4#!F1tGyfTPspd+L0OQQ51)SeaVe^S5lLcCL8u2`u+B;NM$r!~1`6hLN z;w7_t#9aRB8Lb*(yyoYF^iCVwR%&KU?$*p|I^{DfUNV;Cn9R^9k+~MqC!*?9eoxq* zMqEA@l}AzfQ0pP^t8!)+F<#cpZ;`SlG{e3F`H@9Xf4BY z@Lz;jP~rG{|ApG$LW_Sw8wURdj2&p8W&bAR1RW2k{UpBj(|-qv{p)iM(BD|VKC<=` z6-;^ktLnp_s9=@VnSY=?MfKJHK(GC8i9Njo4Q$lkB-N7QKLFf+$146;ydbhz^k4X! z(2rs($$y6|8Uz?6{bbDcQ(22K=k8;z-^`v229W*#19$o_u*r-9yWiUIeT({=7W`*t zSGo_k(I&f;{{itpi_Z}Hq9=2H+54xqG`i&exo2@=O4?uS_W)|jU!MQj*Z*ph_;1A7 zjnUtRPj<}V6uHK({;P_r6x%9tDCQr_5@^jeC!YQO4>E@{(MZ$(_xPgPFCu!s=1*o5 z^FNFI*GE2HskS>D{3-Eas^wC4^o8=6zq?#7$+k+_O8*x@S@3W93KVzb94#&Dtr=IK_Gs^vJNDwtCi25(mQmLvm z&m4vhIHw?)*ZO|wTeJ?w8oLK7Qlmj+cTcrY|ASkdI@vOxx?Q!I?qIYtDBkeF6z3+N zp_)8*C()8+aGPubz+e9RlON+RPo;A5H)4ONFo!R0ZPsE9Kl;VsNFuw{w12EXZIPy> z{?^WaR6m z3lO}kXc^j&cSGG*?~5hXpM2Tf;m-4QjSp8NtXH^s1|_Z*?Dvw>laEL7|!Z zi%6K^Eq&%y85D&wW=hm$XQ{MZJJ>8H(kVH{ze1=9>5yBwu2OelLeh#y=IWq<_NX&! zM6xTd*a{h9DOqjQ8#r@AY;IUJqE~fJd|fPL-wAHEN6vI*f4|J;ePJt{l2r-`E}0U z-Mw~IU0vOK*XpaP`eJR@aAW?amO`8kB_xn5HxKRG8J-qxDMuAE%^7K5Ut;?({d|Hg zz4Rx=Z9&7)+i587{GZ=WdTL%)+$bFR5^lX23n(?zem$B|Ty$ z)vS;Khgt4+hw3))fU0?N=4SGjeE*MV0Nq`rcoMq7KXTCnUP)I3;M}7P#5v`MvwGn+ z=f4T({giWr!pr?fF-d<@D(-x)2}mM%a%Z3hFVz^M*_ZW{4Fl5aXL8GTBEL1^8N!}x zu}T`r@r7!X=P5V!duq&b5g^UC4qf->5l`vXGEMDtf--Yg^iQdL=zgDRFN7+Y}B70?8 zFdmV9{?uQzE;KZcSL-7B&DRdxe@Fi_=>+pVj>o@p|An{h$wxG<|5*DUu+cloe=bQ_ z{?C*70I`Sx-%bT`9X}RssVVK9&vBm~@$Li>a6UWPa~2eDsaT(n=?mKy^>?uR*$&}w z`~{_T6ZW9gshc$+?PUr-m6#u@k8|#ACvJfkU92=VQMS#!hY9D$c9rhN zh|+DrXZ=m5Y{&2seJ$&Vv!)LQR3o3IRoIFYsCr*cD3ED@dq?e1l1)Teq#kF}fOc(@ zx2OL_tmkvfbT$7^o}a8yH@Rh;Y337Gmw8J6=wnDm((I8sz!CK!lZC|dro>Z6$5yF5 zAhY7}VnJ|h`ssVKTiHrZd_f1Hc|9#=pwkE)`2gd7mT*q}2Llq~|Ihs0pSr$<#s+N6 zhw&Ur*eUEk9|d=U==f%ocij?3r*lMTCEM)LrHHfmFxAjz#BiNWVraLtX;kj4+bGAS zzXgml5wom5g7?qjgv12H5?cBd{(-`JKpqG=6it})Y6)Ik>e8DAR^ZjeRPc6aZcws> z&i}I~{$0<2_a`h_KPHNib}|3s*8dp@qqoCUtUfol_ZreF zm#SQUzJW!{Il-kZb05Q7xA}FLW2HJ$(4?>@7`b6B^Z z&`N$B%B4Xh;!7K)UQ}J@HYvP)kFnKekwhp_YQEuL@^KvPA+VBxs^9OTm^(1j`-)WK z24c^*izNC{$*Se;bQjT8aL_2z@_jRHRC5L6A6E~QqW$2cS;$BKCal5x_OAQA&m`*_ zHn|D`VJAJ5x3Uu?BjtE%dw9R|`6Bq(Zp!?Vy<J@r(V|5?p z_+9@NeXKluDLnybWM}5n*^to`$>lL4^uN>CSLpS+~Vin?(I1`FHn9?@ZZxMYMAQj zX^9_J?$*t$9}`FS4RMboPV$2@C^q|lrc&5KbT8iDWFH5NL!kJPM145_IkG~htSKx> zs0M1HU%;6=`9tEjxZWgcYUb93$7?ps5UJcwx-s$i#k8>oPx1H0VEeLUmHBjjd>E^H zXx;1*9sjAPt1fS(dv((-fTDFw^(%Z^yMCTfaNnXFKGNjJ3iltk(ktaq){#~bK>dn- z@;dcXgf;x3obNsPUrnJmzx~OmbhZg!=A1_fu=_^&M#3&jB4xi|S+2ta2d& zZLmz-pp?t<`7L@RFpH>R+^87?ZCQ)0h`>lQi!!H;*`e}<+?v1gxl-9#uP901zNtFM z?Gj#+nR~$%g_wJKO{gI^%>MZR-{-;8Tddvi z1o>EtWWXP`+1+*vHGT5Ii)TAdb3)IObXliJ>>*_EsdbMEy(wQuld9sMp4mV6)#m?n zgeCxf(bHR{kMnD?MQF|CH{V-UR4<^y(g;d@hBeCjPQzxnm+-q|~Euhg~OtEcgAKtKA#NJz=~wQQm^64oqZ zO)@da=bnKVb6l{Ufzxupy-0`swRi7k;q|@ExuDryNb(S*+FS9?uQ?FF%wwzQjQ+m~=bfylK z@u$igKxy@zXS3H~@3lOxat@5mzG#v$IY(I$=&exsG@S9jXm1yt6;5MWDr5I+FVfTP z=R554aaD4AW?_-nn`9HDQ*nagcfP(|n>7|hQypB<5Q+}#vs1j*Uz=LaO{Yy8GM2tK zF35Se<}3N~Ba`IPC3^a%D%eZ+n-B{mnKgZce>M+`ItZEHmz&>r_{_smztMXq*sW$s zbJo{jgv6YZ#(w~$j4Net9le;1h*uvdTqqJQfDQI%sMaA#!A^Yc+%seln_yU_K!p&_ zF!rA6_U6_7;tg`Tu`lm45Npn61DY*~A2lj`PdmzQ9{j$prz&%?_uD3Sq7f)BGsI~@;Qiy8s0j+Z#t0$A~*vN-nqB#nFu$@frse>o} z`E6STU><71)&e)JbywNBxKk|7_D8z|L|Fn(&uamy`x+U#!R`>MTAj7T7FLs3wx~gI zcey#46DHfqNkEo7vRJ=Njz%RisFJ;>t$5pln=K4{}DD^rc$9UGBR1->rv|ZOkI#eokSlhB< zlrsruDD!08{*_KW4b+5u=Ia%i?Gk z>;B1Rfd)a1R#H*-=I87ykz)t9?@KYW&#s9M_eo7ZE^{lkm< zdcjV_ybJ8k&GakfY&0xU7V%+hwhp#iyPW2YY=X@m2b$nHveMF*$8+z1d{HU0%+kTN z^3?T-R}||tyHyDJ>0vsRu|~kl15&G2P8d()n3e@YaMr$?P?0W_EO*%oRImmU+N_@8 zpHQSs_t#f@)GuCVNb(1v*PsOn&An4q0WPq2FMew=u)AaRj1_y3k@HPpaesI>T^dvg zr6_ux>*}GG;5VY)p{DoRZ8900FP-nCoRv}OU0bpwo0n>>0YAT}-cVRf%1cc(Gza}d z%S1qxuUla07A1(a1G5Fw+`)lcq*d-7!Zbf(VPrGtVR9SaC6SUPz!}wb$k7{sH(d;q z<`WG5f!Q+q?ca#!ws;i`I7MdpCFKJ0{!m>ouQGfNxp45`<}#l#O3FP|EZ-u`lxoR0 zkb2?2zw?XqmN;%yE$(RH=J!PdL!{61pi?iIs+_rpF1_>TA88w^gPXb)8~jf+!+txp>{zU~w#vnm#ojTSTP_#U}$HTZd~#G(PxLet*TCni_{oDah9R zxcD@Nze?-G*)1AQ`}Ib%_xMenY!I(GV?HdPpD_Rf6rPP-B>PW#$beL!OOh>>)^szL zEOgXgruj#@p-~Vpx&cF0lV777pL{hI-(~}=jPFOi*bX+IaI)A-Wrs1OE1rYzxrWt&b z>*60u4))BPlfG%+elP5IBp7Qo+TP?(4KynCM__%cPyaT<7$fQn5!R0K00(6{EVJa; zp3eDu^AS)JAZl)J9oe~>)js$0;)xTo!Hsf0_B#Di*<7a41dG)NUH_`iR(NvW-(^=- z@fT~2Hfub4JPX3EG7h5^us&cMN%_kZ5>=gjoz)h?Wm%0&dceQ#u&ni#oEA}CoxNTA zp{g*;!AF{~e3a6;%mndAr@Tnw!ubv2YAaiQAzLU;r(q=_n#eGrUd*knGL7Zfjide? zt(r!~6jI{ZCRwLLk1Bq>h@rwdL8+p7G{_51`?Gxld-Yd7+Rawk$U%H%C2g7AOM#xs zEb8u41nz;{A;ctL(w;ii)d{l&beYvHM|B6QKYV2?l}!SV{60=Dd+*O~%KG0({{KC| zY+*o1?u-G&dF#*GLL~_s2;KK84>K#=nl2}1c4Q`}-47X1c^9<2eLQzA_0YL(nLUNY zeqZR}#-#70V;)?gTfhHwLfp>ATRBZe&~f*2-4TD!8g}gK=C9?|bVNOUtZ&(9(`SE98}FgeADr6G z;t4C1pa+ih5TQW1C4XO(#_9vbc}>&RbjcZkz6sRIG-ImD9Z$=}8f>1TeL)V2Gg#Pe z=y?1$BADsQ^`*6~nDqJPf$aNLeftsG5K)em$=@G)2(E2 z!C!SAQrrGmj20h-*;;!eE`A9#|8Vkl`LOsZs%`vx5P0_P2(3?2`*5&DB-j9%95dhI z#soiJY_*&0*Ct?;eCD__G3HA@mp&9tM)wt<>Q5}Cc6j+3>IG_FImoDKw~;c}dO$l5 z1vhdvGDS|#`*~662slx}=is0F3YVs-H3zt+tdJ#Tw`^*zNJ)3O!ijiTnOihP-NDmc zl$X1QemPs{Hj{}{bLcNB%ZHfjeA=}ipZ+?KQba7XIeQ%!;4>+Hplx6_Oxx6s%RTRo z_-MLL@$ND_gJzh43g_p_?L)t41MA@iI(~>8-``u_e4# zEEI~Dqhk{k`|^qP?WmnU0p5R71NlbfV_}0-l-f-;W2WL3bvt8>#!!fAK=ezI)8?`;Cdyl}@i59Ev&%ne zEPpIL4Xf4#%cu%1*s6M#8Pm zU@Y)sM=mSgOtMifp1{f5Gyu2CU|2!*k?+wFrpsbS1DI|9rN-7*y9wM{ML>)Wh1yjc zOKj8%hGBct*kpDi;W}-rLGdYS!ac#U#bpUbtdF!85}jC3PuPjBFJcY;3J4iaT>np3aaD z7X4PuE)>Ed8A37+bnfZoEoS3eM_=w5h;5mgedc}WUnmKlnH`)$Vz6U8u(qsSbO`Y} ziZk%JiC34gl~{#dXOs70HL{TIm7VkEtq;0r+nvxp6KKt*?FCmxnn8m^?U0 zz9Pr{l1*yTf^FSs%V0c-LFu}70qcXNVAfD=FM(B6ig|C=ze@rB4*1 zlF?-@#!jQc_n0pT#(8xyGMJaWKt7}+Oxb=8AL?z@Y+o_Pl1JPn6oOV%RF7*a&58fO zv3bccYDAA&E!4EVF8qiJY;GUi3#2BQBSrwb3AY82Ul@4D=$lS~;H6!Lta!<u-Np?EA-my1&_i)9x;0W3ELdV~E4!lpyJM!s>8W!PHLLXz*5K zg>f6LfzXlWbC+plRmkwk>kO#kUzxP;ShIx?cNwWxnXp^5?>D%$)1l|prA$0g7Zs7; zTp&t@?v-b5rlS7z8?f^$`U7HG!30%2;|qg&@6k5jY!J*yBi(BEki)(*(onoXE4r9Q1jCK!^79QI+-^RF9pB-^F3G{m zznw6At4u`tRi=-C)x7#!jo+u zL7QX>L&g;e-e%LaR$(RF$s|;KrC&_Rdb^;#abHmyA&O=vw$?Eg9W+CC?xGjh^`EIh z6ac)M5o7CsLN&uYW9z{t>rG-jU0vv2w`NONOtLEu>NI?NbX9wm@n!LtB59L_|&kZAD4Hg zmNqAQqNtw9kGO;hYCtHJRcRhBO4Wt8TTx?8R%1dp_^h7J=(zd(00)pd&cXq#cf4+H z)8za{<)`JZW3|aocNifnAyDM>-JD-gYbBGr!~2kNn*H>p@YjS3uqjh2ELQ><&xTaa z{Rv6fAa3u{Go>tG>~_oN5g={TwOytlCl010$y8+rr}Vx?qRjb%0&&Vzw!@oe)TI&DC%jokq znXU=P#rUbt-WI$^$1SzJJN!b4{oMQ`{%sFpS58- zlRSt{(bS?*+r7K3*ILOFJ@3tz^Sa(nC#(KUIVHyR(iAZi8W&)kV8(HfGPP5(h#*C^ zxDZFhzwVF3ajAir1?%as*MU~6`Cd)q@Zp-u1us-f$Ho#|4VL)W>p3cza4+6SQ`Hv3 zaA6h-sZ2T~r%}D}gJcUEq~^hW*OSgIhM-rqq&M`HH)(q$@mEiodKbx$S}+3UK@wu! z)?RoLgGQR(M^|j_+E6odFU#|fpz?T$- zs{M43S5^ubce_8lQY}`Gu5-T79`6RFZqNR$J*3Nx3A;Wyi+B9{ObQ{lM}%_g)2fh8 zyjefYpm@vR3PSrmbgE-CTO-mz@3CiXAvMRVJNV;I5+HTtyR6v<-lo^(%?>R~cOH?x zctOafRr~N(Hp{b@R6>(I%6W6=Y{&9{*(~+s52yAASR%c)H}etb-}G0Uw?rnWheh%) z$iCgtO*(-z{6GD`)lTmYyiW5dH08=Lu+(!!5l!x);4X97t6h`3TQ1B}=*L0jV>+Ss z3tX*_y&%q9!-jk?OMxv08}I6J;GgVmuuaJgoqiY zF?uzc3%A56llh&;>I?4x4I{6s!me3ki-ji6qYUF5OQZ39ft<9Kxu_mM&XrszCF@Pk zbS@6LVarilh$g&=t6fYJK_Ii3>J>gDc`BlCsp1L9K4h~*l0Czvkn?I^ooO~bO)UP^ zYVI$Cd8EaC-t#WwTdSLR-ux%bElyU0ATjsr4ZFp^x)XyH%u5J_uUJ`uBs}KZ=YVd6~=4NL~t{1emuv+5gPc5yMvq7 z#yBRVa|*C!a+F1itcg)X1S+nT=5b76Vg z7fj#!Tk8FR7$EC2ANY@kR2zObI`PE2V7VRHzL`4~hDDg*=^gMNxZ53yk+eI5uDzm^ zTSKdflW-}vOk#6{*HPi8kJW8Oa=P0IZ_9^4*|Sjw&Pigp=4aklX&=AV&cDuy*DT!O zJbIDg2N+{Zs{Im6xwt#cL*L(iDlXlE-*b$EsA-iwGWG4nOnX@2N=Cjl_5idYqZ^ZI zz3^ga=ef~T{Z1awq040L#$=tpa@%9O>Z>mZS0>#yj<70T(y@{Um3tk)vD}xB$LQ8M zCZtEZeohh`lAgoe*nnpT1D+kgBJivBZ;mvlH|t#4Gq{$`k6)m%)r*%uhYxHlE;P&I z=HsuZ#(7~iY^I{XR{g8eHSq(U9f`#~{q6k(C}T)9r}mCvIM%l?!aix<`zJ+aUyqAK z0R`2cK?%be&FjuW`@$bQC3@-3vOUvn0Gyru5+UZRy_9Xs%rs>{Q<0P((j+zGq!};E?A(1P z7PvR(BN~r2DKC)Ll~9NV^q}c2laf?Y6g;^2!xmh8XMGvass&HV28wQIW8_ zVti)TK7IPy!E|i^FIN^m;#zb+`Y4}AD$vzruyupGUE~comC-s=0sAhQ7Ej%${d8kC z{YSM-fR498kw}&~Ek3i5XVwUt=g1iK3rr4PAey5`hzs`-_EnjIg+oqUbriyq~isWqqr6 zQ61uaSl%SVwCX2zAv^h8$bC%-m1m~${5sh7bR;y^DO~#WweNGV*H`!A!vuPFb#)Iv ziJ(ctTGc7He*c<`@|N^;|Le&IRVaMvGH|&NQ@pno+jO$ZwmAJ4W8-dTz4o z&Lm@S=hSu^gcQ@qY?=A<=NH1X?K!W*!dQjTjMhP6U@Oe4ea)|ZKejR{Hs0j?%`jq` z{8&Jk(s?ggA7e&rr?$U8hQerWS|kz~Iy_LhN!ySj{F?++`e|H3;YrsKolL@?|)wAclGIpE+ahO6kS z|D<6iZOP$$tQ`$itczJAcoM@n?dOOs-s_&*7L*^@;(FW|TA;`u7u$MR8W%E6y2U0!VTnf{T;g;2 zRqNm9o7)@rak$NERh^Iiru8?Wk)9#C0&l$NwddXG+sox~&RQ1^nh)uE!`{!G*FI*kPWQGlElzkBtqQ|9+$A%T8@smfZ8}t~^OH#0 zX@oMR3dthuyOr|fSjqWK`M3kialuUh?E+hci+>#!NLTPd3b+;}MUwp4Ll1nqA)vvq$Q*fkl zWzrhYV2riHfW1m@s`;@4JRHxF{QljqV6OF~L~Qp}D`R_C#5+kYPueRo;p>m&dUO$# zbe#R%l6?!*?aZ~rLNaLnhj$U>-_xU9dUqHu``_1b_v1AO+uC{U4EmwW5s0Wv^Zq&q-KDd~v?DQ-L03-kxfJu-HFJy8pFIJY z?;)mr5NZDTC83ceycEXaDa$MZq zA>?Si+GTkXFw<2D4S*vdC!e%mM94dPm}o{yezNdH;bd^x0h1y21CF5F zY4<*PqY?Vznd+EQThEQ55)WG~uW8IeHAtvW3FuJ@*-t*D&EGPtelLmE2F82O`@A1( zY_;|=Iyszw&GvWfD17$DM(3FP#I&@?&UL^+)#J!#6jS_$UmxLt3&Wz-RL`%*((3@c z20{B_fl$OXN!&GsBN}DjCg&tIv&BWcJfV#kE?b8v>l4;F!=qb4_$GlBC3JmAWoQa~ z?3elG6jygQLp;Ftm*&Ev?XOFEnqI8iYBB$wY2!F+da zR84)p@6P1c$a34}y^2cl_%Kbt&z@+buJQ zhs8aKJ^u~u62Q+`v?iKV9Kxgu!2RboUN1InHI)?xuoOdC#s@s>g4=-}^yXj0&P6PNFywh zOX;FTNd8^OA;%=i6!YTO-GV6YUJLapP3UE^Jgr?Jjz23^w929bt65X^w z1#=@o-P6#C{@SsHtlgE2`)}7_XW0b{z@6556(=fW;XPdxfs4=-&n$ziXo;?+{R~rm zDc8rF-iq6!vUrvpFh;ADT6Npn6H1r!{uzjE!RCn z3tGCp71ZDXJa}H6v8NB4G_UkV)z6E+q%P{GAzfrd;EMT#`&w^u)%I|qrlyVG^c^jl z?tAwQ@GMb}vR^=(?G_IuMpO@x_s*TID85J)_uU6tA{4dsSeQQ@@0lun&qMw76ZcNh zD&mNj%aAY?yxtfdm*_+V3bmmJes}3+4%a)Wk7{kbicEv|2)$-c?UzkcjF@6MBgOr)E~qQ*>kly?kty@cGODzTlgLDMbl zsJR4CulUMj=}Fr8RjsO@*gR1Fgm3hV!UYkuh&I!IZ?tSt)Z(o$!+waTH>0<)}ek`l%e=PdeXf>=t`=iW{EClDb0+^sl;tu z*vrlizc5i1M+2{~WmdMg#Fi=BbFGr-L-w@pRVL6o3xmFfN!F+w&ciDt9?2e^JNR2G z4c4CaQ|$|5Zaw-4o5yR+VP`?G4jXTxROz*y{p$-UtpCWuBZHTcN|v#b)KZR_cbskE zkW&Y5)QSM>IzuA_>@|SMcouVFUr2(4q1AWq+P>yej+!eP3+LdoGn`{Bvf+44AQM>< zIi#VU5(p^JRz($NIObuayKY}yg?Vo4%Huk3KnW4<`M4Xy5B{6_hS2G zTVhw$I`=GsX9N~Xdv7g)@m;H@-8fo|-Fpjod>U(aHv-B$oqLF<)99n#5C4#Uor9nO zT5H?J!Nd66x??}Yc^Z8DBW&W=4t&Ck%TMl&gIGbUw|O0JH^gO6%w*8Eyn-&0Y}6N? z?kHeZ8EhQ(k}Ws^k->fDt`Qe(-#vM|5#pgCWj+3bF@JPkH3+Hes~fhq_p}>0IHLIb z9SK?Q^Am2o5l{YKPPlqp1R>b?zCwh z{8(|K$J#Nnx2EG4BO_bv9ywwD=ar?^UWcTH6dDte(eF}v>+}yTod;LMGyojE)@%(hr@6%gMB{^J?RbvPwwqI*{$oJs>=@e3+Le zgKjOYxOY!nCXv(wbwI*LqD_MG46zs|;Rbz=Lr8oQbiz&uka-j zZPgY-?^C>aGBxEI?@fllaopM0pwW{{>>qLCpEs$5zpcU@a5nofYsC8lPpiAuf1OsJ z_$04J1V0`Zok7w@o^Fv_BKsJ!W0{~0b{a+#XYo7pZLwy6^x@)cG94G|3!F;(}wpA>kU(?-K4h5LnuMIJOgscHerg{zg= zg&<1c7~ltrnZ_V?4IyO8CvEr$p#2JsEko(?KkgqQR`sTPa6>KqiL3p|CX^-fRgeC; zO-%R5y?WJqNzlespqWw)h-R&yPXjKE*ria24l?+?+V1ievt_H5|6S@vF7*2)WWNIo z9Uqn(AKoS3p7NVOcCKEZ?6R>jRkY9(v8xd5D`r6TM2<=f6do0 z@xBSQQ$tIkx`d(p{cIz=uWh~jk@`b5*bgB`@C{ub71ktmNjuR(F&AFZQvppP_c+~a z{ZE=@NMBT6oqWJtNdYCPe%l=2{Y*Bb_z1G6N1sux%3FEe*NW6XAYVMFh`glnShi5G zyJty+d`g}%M=X^2Ap=ZuLiX|!(ajf5# zAC)NM6ahw@FMQNJnwC?TyK_fC_2*~e8RRd? z`~J3iWt5j~q!8^Lsy8;#@!*Q5-rJL@$?1kO4PYd?xhSyGFv_`(Zg_LM#&C7{f&)$C zb@Na4ov*1Org`#u#1Ddb#0(DORGRq((`o+ay>|?t$v%jnNL|m$3i#S1l+KF|J#^FM zBA;OfTGx7?{)T0hWil7bS?CS!KmGuN@Xk z@*q8Qd}z@!YtFFX+~nm!;$HLcspSxad%NR?=Q>`&C9;u;LYuXlLUgLJ1H!tl;xUc` zFT?LkINmq4lyQuyJM-3ciw`x3lYz>hYF3(dmV~Psa?Rs^Qi&bUHfZxMTN#SG2^m0* zP5jK-b;;3>U+WX-u1_OMH(_nmsvaAH0eU+KzGm$mu^jNTUYKp92UB60Z+xBzKJv&YAdwd<2%FGnF6a^zL?y<)T%$x6fkkTo_>sV zdf?-Bm7Wo!ST93S@$bFz1NG>vOF!=8YP^*a$N_0rn$Y4a>ZjeK80J&MEENx#d-yWu zC*3+i^Pl?~`Jf$hS|O!634)Hp{EtsLcyPdldmsHU+hc~90j5OJ#megn;mHv2)_qC0 zedw**dk~14$3Ot%;B|NuQWo%-F>GxrB|X03^UkgiK&HQe-NbD-SUh!Ok_kRbcqf?~ z@eu#fpc+3P^Dzr*B8n#V+HG6uPB+JS%pqx%!d4GY)=hLbE@-)5u)xiEJ{#R&A=Zs# zSQNnc{>2$_crrg@{Yiy}q{#~yJ*qL>G;Ny*S8_!vHKr6<1HMdggi_Pl==xEe9;)>C zZ@1PS@*-$i5!nm(Z+`nC%Ez$nWSzf>nSME%F;}R@>-JDlikeGwDBK-_n!tz`nyHw~Sor}5)C4tdc>&Kv=>_BjRnT`UTR*sfyXC?qBWPe&fB3s0Nxt~= zZ{AC-b+wo*^~~K$rBWKXlGUp{xu(ucXV%?C=tgDJABqzB;%)k49cbNXP$6cwY1xfM zb{;~BIcY`4C@;EAChM@_Ftk?mA5XvMmDyNsuf;`)|MaX$vUHtDBWl0LpMYb~I8%&U z-AKIkzvIXPzRbvd$gFLfm(>z3E^+;ew&4C#a-Zc-U&Xep=v;}C+WUu9JA0I2i;wKR5j_3?(-~0ntrhDI_HV#8&r+5oqEUr zUEljJwTNFmRRcmD-@P{nEpqGXa~nHxG$-9lFHP@i+YbNpj~jwZHD<&xM{C zdWuabS0W*@#}7v*kVN0^E5FYLq4k60i+tx2iZ2}RQ3|tnf|S~TVIbFxG91==``cZ> zq0?`JX5az8qX`k={akXl%*1Jp@Ym~yJNy_fg5L}*u#Q0}A|Tk2-02v=+=kiA1k1d` zf?p~=9G09oepHEj`l_e=JzV=+CWdEqGj*ho>4{_g$~PcA521>w3`UEiBZ37|OQ~ph z;IHb&G_5$t(zmG5&ngd2!#bEi2YNpo^_Q66%pDl5-SHsa%khMuByZfov0&54&D%O} z-WU(~i08DE6!}k1H~9;(_Pg?NxqUQOhC0W#W1;KS+dD$`n+ZRnEnJ0_omCzF+2Z5E z2)d*QiL(d%Ccy3Z2Pv7yKncc3x%t>Ovr?glzWaQsntRh{@1o4X=!4YOLtKBgX{+C} zO&wEu$9n!PiaBHY3ND~4Q0U88VRHL9(GF*S*jOyAZ7XCdtX{_H*J^uo&Qhjb|5YAO zeZUrtdk4^ZCG&9c)PR6g5^~bkR~8nwKl!`GDf9(!REn2FQF7NhVO8iu8=djT^w8d6 zC@vs03i%{F12TD5tKaI%d*}Vffr|?C^I^;EqiFUAz5JW@9U8EWhBtel;YS~}7$Ozc zBC>YX_8lpY)}@pmiq_%^aG^3a-|D%e8+;3IDPFrt0b%FpR*3^qw0`9pBc>ohG5xAa zK4qxyi%VX+YuE->G~^xmZ}A56EnyXs28%5Fsy9JD(~75jd_|#j;h>iMV-K^}t>)~; z48JHBUZ>hEy#X%(YZOdGZ;XRFAA7v~+an<1f{D#uLl9t&nF}AJIMez$h<3xcAU|Ha zL~@d$w|)a`q~PYL8S>i9@kP)2su27!(}+xHdnTDQjwHZ>1=Ky_<5th_P(01sX7F%!zZ^!Qrk%E0dqXfypPyyvCRtN6YnrlF$qo9O8dB zkP9#>qVFX*Wf2>6Nf0<`vTz#SPXx(SiJ2(Khxv zb|BLq=Mr|6zE3yfu?zp0|61RkO%jTd^Yr|CYdOs{V?td`XktiY(De-NECaD9I@8Y|s&%ws9)y}|bYG(fq2v*=3ZpkU*d3bh;<1Wp!3>d} zmgE!kn6CX4f#$Yu9Xs?-ff0g;LrTDNR~5Xux5cuY3~N$bznDlAO!`ubBYWxXFV9CR|pIbjblw4WVW5C z@w3z5Rfkiceh35CWSBk>0d=JI486U!SK}z%@+85Pd4T4DB=vtgKe4Yphe*Tvdg^4& z|ENRr=Ysb!f5L&@L0n7d+Z^zR1$$lZ^O?k2Q)Tz$Q=B(V6q!RqtNFPGTg(iVx} zMPmyOJ&v!#xd_BXj&Z~`?%Jtgj7^2nppxp1>#2Epd6JXdTa$E|(gJP#;MWV>Dgz?T znF7SWeb0$+_p*P;L7m6!ICIima}0Uf6UIkbqMbbFmBy6J+seHV%!9->lJDFsO~lqE zmu=8A^4z}=5RqkDPL;i;ziu;eG=AQq7U42`wOQm=g-D)W(ybr(EGJm3Yg^29F5gn~ zMbds+@|n|(w+z#U%5}BT&S%msXLq?Wayy^uFs|i02?M_k%FF0_j)3${>W*7NEQjH+ zuBTNDyZ3bXfyAmRXluo=S)JCW2bH1k40~217dN-?aczpG91=QDTT)pnQon{(+>yx_d$fln%c=#sbX~td zKo|P4W)DZmLEH3i=snjq2Qc##CV}|%x(%YxyBTCcU|t&cnvQ;d8px;f*e^m8`cac# zdVALjx@YX6;nj7Abr1XDAEL!;at9GNXRV32OHdsaH1#uY6JMJN*kC>>ml(CrVRD-Y z_r;3+fXd|W1c9ew354k^4HCk{W)C8Ezjv%^#m&5057pJl5ORTjx0sXU8C3No6P-8> zuxdSuWg@@eFFmle9I@VJ3Y-qmvaK|s@BZ|3AGMn9UYsY!dlbk4sIoM4VP5en`KB4J zTYYx^NmLUsHE{=XWZ(hQ%J#|uY^x5M^~II6R+S6}Q<0nn43?D_riKl+mb*vkG7ppv zg^^lsh3OUrpnVYonYNp{V;8Pdw7aNIXc!b9QRJ&IN?_kY_vL8)VCUBz@*Q+QMMNA}t7 zrM-nKOv#4A1jQkm&?J(I=h3J|knMo%PH*H{L()hTOTr)kw ztObW^cx$#_%bLmdc!sk7cgF)YpmL*oVHs&z*v!>(-=H`j=*#TG1HU{?bx+K2%BH>* zTzJ5Y-ivhCKB*AMfemgu^?XoH{#{6V@doHl3cUqP9+hU^ETd(MhgH``u(k4Ub5wq8 zc9gR4zsyAT^E4X^>dE+gzwz)%_9t|EA6#|!4ndvh8bL2s?i{nUaB0AA4_ zlT;m$`vFbA3&U{zBAM7(+xoVkBo>UBgfmi?i1L>Mnf%ac4Q)MKM?c@o&2%JGA)UD3 zV#NvAYz(5<@kunhWaEUW^3ZOb9yzDs!vqZ|7%9ndWAx{W|`8#))Z z)-#iQgm8wib))&#VVH4tZ7ff91#ULoU1Q--p~;H&W$ZqH2TrSzbjv!2T6FG0ItTgd z$_r3{doLT?(Tae~bG})oNwWC32*lhZ-waQ(k@aw|OGhg4oZa8CVDh@dRJ$$5=GF6% zAkopR(fEY(a`(21a^Vv#nwZMtEpFxl zlfNUnZ)Lopj`;9^>B39O%k(H-ac`&Irk9y4Y{EbKM6be$f3hXobk_DeH2UHV0HJQ8 z7b?-5cG^2D)vC5Fe2xJ}GXty2J_{bYOWqY>hZFB4>}q$7ywj~FF;{Tl=tnB*C#^@G z+bqwRAe`9yQ(;rlVka7-#G(}oA=|c<$h^DKfuoI0Zs9=z@=TtGIdMvpdHVUyw!d6? z&oA1I=z36^QJKP?c}=vMKAFc;rk)zT?;6LwF6*~C?im-(?bBq?>{^Wb0wP@AlMg1( z6D)rk3#Aj=Bz+=O?3C2~OOo-^v4sNMH2h@uS={^&`s5<*X54n=_5KbvS0&XZua~=G z47-E6=jGM3lX(-OHSrAUDu@jqG5JfyAIf@=i!~RN{wASJ4Gm+&bdYiGO}fOE1enI8 z+s{4Wpa!R<(Y894chPO74-~`JvZX!szZiS(Xt>(`|2JBQp6HzrBzo^e1Q9JFqW6|y z^j=1d-bL>uMD!Bf=!PhxBnE?F2BUXIpX0gj=X=igtn z8u3ghUs>I|GG)}RVuQ$%M%QWJ%Q_QE1eb15E8C*-HAznvr_zh1kI3wy%;rN3MYjt7 z0%3#52?L`SxdX4slKXhFHCdewd6Is!=bw+pSS&7vYM-4P?W3uw&eEr6hQjZ0yJO`r z`TLyxx2n1QEFvAu=DAESRXe@f>^ssOX4 zs!Y`QY&$KQX=B0L(q%Uc3pIT#$JnU=vTuTS5K774)lO@Z1nO%)!``P~eW{V}SQD|a zHbqJepa+1u%I>=exanujt?NZsntTl~%jk7+YLrr-C4;AMhCG8W!H?JYuM`0IEeUkj zY``b%yL@LOw5u#pfvRvhQ}M6IR%5deQHiaF>lz_4szar_pDtDPEb6zaxrKBTkPmTp zN#iHeCe_uoYysMS)2I{jv%g{)*ROmwEzR?^J*K`6vE@53sJ?)SUwSXOsB9bL?zNoB zMAlX;!SOx=iu|1f)vu&QCrVWlEAl?rz)bzd*@U&GxN84E(MNLXAoZPcrwG0h<;aTt zVz3ztwkhyAlRCUKB8qjkQ5?R!r;Z811`c27_I@J-M(dQL!JE1vN(;<8CW5b?Ps7QW zcECMBpEuLaOjDzke1XGW)@xy#-2e!-*Vc=NpXfX^7w%(FQOm&ua>WT*_@;wn#hyV< z%$_3w!vag-hv18@W=E^?{9|;@RsL0mkSF8)o*65RSFV|~Ph1NF6vQKKt|vFAD>_z+ zZ*AVf=EBa%uR2bPMwhSl=}HuCK?eoJZn9qm9CylH?wxeSTm{Qq1qpw(|0=4|$ldQ> z5qWx61N7m&1wiL;d|jivz9YBjp$4)MCLi82Fh1cTi%E$3ee`aAX)u$-RHO`Ed_J_j z6?ElGaC#Y@RTi~-KyG?+!I-J`ztjz^7RUe5+7O6P+Wlva3yq>a$IQO#r0lBG z#{0ll<>P;rVu$L0#S(2#4Wn9a41tyR|6^EyQ2rL^aB-1nZGRp*f(sT&*mFo2{Wa(*HF$(;U|Ll#Oh-M6 z9T%ga68U=rpECDYl;ty2y4J(_X6L18+<9eQ8(wy70vPx$Uo zXsQ|>A{$Fs@#a6PzvM++vARL6eF}G%4>A6~hU|QZ#0QJ4yk-33t z)9_FHb<;c?RQ#WM!h}MmvzW$@G>lu`7ROju>HbexjGov+2RE#5+ijgW>M zmx=#b;3O~68gxv5=@bi2!V-g|*wde+JuBdeD^(`VH)PD`JFFV3=Wfb7IL1@@@AAW6 zE2PIGuE!UYU~S5;XKG`O2L&sJK|f3r4}e)>Jp1XJ(f>@V>&lqRByiL}GClJtbfnQE zPxkwWJ%;rLSy266}{&p4hdDVDj-JsTzVww1!-yZVMhQCNr z&zzX2&X2!L+g86I!MSoM*#U3AZ{^xoB|GGt-4h3W3)K4DEO!+*phEgL|IhOE(B$9! zWVs>nvZrQV^RiFch!ZZ~`RnGqUlLEjY}1djfwhY)7|N7u(q?9WT?^*%Yu)(ol38EVS(jU1&Qe)l zIep_pe`c_T-kJ&lhF!qWCB0x>P?=i~r?gviu)~R>V&?TJ+Zikck^Hc)=w_~++UjlPLQsB_jM6w_tyGa^)EljC>PQ_85 zLFfRyCN3Ux7QOrhG zNDAu1-#+Db4+!sw`X+Duh9c~Ap3>GhcGwZHWobSgihzhXvjeyUJyYwrkdRQjGEL3w z8u`gCU1tg8&J6HmE$1cpluY&~>j|<^q|BNaV!YrQT;ET2%m_1Mo=R!{8);#Y#=KlX znm;P-$xrKMNTIb$=x>&avCq9TW_WRB%BA)ubG&rW8|IsVju(jYHF~Y6r`%1GQqxRz2sjrR zLJwGfoH8d^NQ>Av$XsyZ(hjsY$AWW#6$tsH={imxz>ZD%$V683NtKgzfU3anK;jrC zAaTU`jE$MsK(o9J{*@Z>K*?Mbo`UF5i)%a`A8b-P#}h9A);u?yaj?~3C}v@;7nKxy z=C6SjoM})~N?TPbnXC#@7}hzvm}x$;dpsVsskGgqJ3rJOk|+ej%1wm*C=mh=KfM1> zH-~GZfMFt5@Tvv(dfuta=2pqI7MxdDEa>7?Ny!gANoOe)fn_m_IOgCv>q9xfF&z=p zug9Ev=HB(Z}!+gR1KjKGd)8|Zp}>J=N%@vZR-N({_SE|ADGQ|=NX zT0+JoF2%{x#1uI7*!)!hI^~2Mkyn!d?WHEGuxwABr8UJ13}Cw0BJ@qinHSL}zBQKn z{7_r#`SruexLZB0v#jvShsUUpY;WQwl05DXan8kM+)49GjI`}%N3d_?_RNrBMcNP7 z5PSb~#yXFeGyR-QVc+Vvxn62Ltg}Q)$1Q}i6asNq4j9+GKJYSKf~wn%fj%so)(?Vl zPWc{Op%FbpqD2raUUn`Lh|DdA`()5?Nc;uWCT;H5GGUFE(&gP)e}t!`t`7XtY_?EU zJk8Hp^Y=G)Te@*hQ%QEmLdVh50cKop8$c3@($Nm9G%N_l*%jH) zn^YT=R>sJ>d=7t7TK>|ml!Ie0cpDa<-+&xJ-(A}O6|zIIY|MpQb*J1Wh}+{xs$G20gz6< znF9jvxw4sF7xc&x8TPY}+fvDpYp({6loy8yfyYNURKsmh{f0Cxsq>z}zo@FPkSSW4mnTG^DvuU&gIqO5l4J;-OZ?i`sJwe(>fHxv*SC5zg*0tWREEtdAH<^KQ8cyR5dS{qlMiw7VX6NP4}nf;Xg zvLsKmg$Za)VEbA<>JFxhWaKX?bp}kJS%*VHOax*k*bebgNCo? zbqQvV#+3ZWX}PJJ9kwd@QdGaO*0X&RakHehn<}9ELvSnbRGPEnc6u!$*VKpu_FALS z9j)3KHMgNb0hwfaa@dP>S8+-U0mn4;(^8GKaWghvnNcXz(f|4G@tZ++{2=W5V}g>8 zf0f^c`|R+?!3mC}kFNzALJIv0e9Y)Q?U|*91QUhCAJ2bv$Q}8sanc;M;fp7~FJi_7 z$)*u4uuaPUzV{Q$R6l`#ve@dERs`qV#D~${ZbF_nrrz-H0*Yu2e8_Qup&RV*58hdA z>k8Q43O(VtDi4DW~g6!oc1u!)FZ*BfR1}T_or7j*l8Dn7k9{f)6K(Nx8-N zBRzjQ(86w<2fcYbzbW_}9r&dx;#0U{rk0w%X~6{%yCK4l07(WQDU>@@z#Nj0zO^X zc&T2Aq_{h8RgluIbu19`ts&!YGr0?RK$8O~(>A;Ph9>f2`j-b!(t^cZ#|>-SkXEkR ztxWi}yOeOXjzdyID!cY)Ug;lwh`}D#Zt3B40@R{%rym&s8RAB zh>wY}UXYBviG2GpvtO(@@sTj3MAm6J6+GD1!BQmprh}2IHukMS~L$W*L&YS@iD}YBnwV@|1O)Q<)`$C zh?;oQOfxo%oot2)!J$UoJ-PhlQ!vr%EGKuKF2KoMtivbzc0E#1?Iy;?Vxv z`rPM1i%%BS$jp4{%6JZ&egpj0J7?1;`L~=O&8dd)VV!iifbo_M%xkbtcq|kSyOfNT z0F75jyA)U+IAhDNzgQ!HQe;6%hipf#Dm`*n909`V+r>ZZcR8KRbqo9k}r zf>2b?jt%Yj3M@TSp}J?rX(#c{`25j9P{a4sd4o}4_$POsaL57|0V&_Zy^Py+eAd#n zqfVt=%Q1ytl%nZyJ&L4?jXkmJ#yM3wh{qL^L_g0V2LlSO(D&ldbk*tZ*$&#YK*nC? zyD5bhW`>E*r#B-g;yle1zcwe0zcUs=M{_8uxc$+PB?n`fy2s|NPdnRYejCiB;#BO@ zp|o**uHxD@aImaBn?`3M*}zcAZHJN+W(fkicLVyO^xsw-Txs5*zZ}T_W!a)`;EgzL6xm)N)UBCVfKe^?jw8 zJkY{d>Lj}J{0%G`)XI|sp%AOXNjyzTZUdH|h=MlD=gwfow>bi)fI%51KboZph?|D! z_&`>i&T39Nx>1YMo-Zi=bv{0(FYS*Mio$Rpv!!!pkK+i|?YpE@mtoI zqrT5RVJU&*r*fDA@%1qnooLEw;c5QMTDawW^WCj&j-LAW)utWXdAXxs%@M>DL2`mY zFU2TmV&vBIymq#{+6zu*_jNNMwN;oVc0|Mh7V1$ZZ+PV=yn;2!q&45AwKjgZJn|~q z7o%N#6UNVs_7%RuPc(2oF~&k~NF-$ZiVBpEwIQ6;tEHk1ZT*I5Q#{jw(tI-FOZ zt%xkpHt1<&uK=Q|b?v7_0LCAuX{J~&{6PMr%3BE@sQa7)Rj94#C|EHymLGO*f`5*8je97>m+QcVNQ2I-OEy3hoR)lWQw^iEW5KN8z-ehWZ_4)xvz~P5Pwm0`iWql!9T?kVu?fq9(4eF&v4|dgn{PxEe0z zvQIJ#~h35<_`|24kL*cYAHZfaxSJ=*FjcM zvKvg@$zf+9jCDj|a>j2}*)If3cGSqaH?LO$5IxR84BuSNT{=3w9*sTYQWSEjW+^A? z$;5&5gaf$Kds&E42V_$t;z0UY42%En>7;nAU-~M4)N$6pM2{M3Z0C}t&dpIaY@$ov zqJ&}$BaXoT_wfeVuaHj1ZDrN_y;!-BoVDbbly6fXKZ+kP;v^ zQ}-1BcE--t8)^*$Ys^b=GDQX%!IqW`RcQ_q%=3!z$(FVTVC^cxwD_nMmy3c=hS!f zPW)@ys!rNW^sM`9dD`Riv;mhz6)FCt(Z65J<=zo%jTkg8Gx;>JxbO2pzn~S3_Za#` z_yT~mi1gJ9>96@@0W8(IsaDX5{{not@R4&WN6UX17pVIZc z+h?5-u-7~_O~pR6eHP@@7*`JP)4Oo~k^FAN+*n2l?`G0B($i6c;RU@1G)q3x#Rch- zYsS{bbs6*(?p#`2dm!Y7O75g(vS!`^zo$P4`{U!8z`kEuS+jXeWO_aWRoSd`d0eY{ z7rxnH&kfx~1Z<;*E`HQ>b|plzDfqKAU4B>cb?3HHfQprQcU%wP1=8rgj~s-43zHrA zF>`HwDpm3i=^Nr!hRtC%U+;Ppv3*C97bF2{D{uLOnwa*8m!Qg{lVV4|OtGwpU53nN zRJA{`7m)1cJd*obb3N>>!Ju?3{jFQ*!rnVtg+T z{J%F^I{B`1r`cXKCMx_#8~5@syEM^}@%|2%gTr+D{{nmz{7ErdK6-%i9^e{|%RgpW zUvk%a=2&lZ+ulH6Zzk#gpg^LpleFPy)Z{YEx-Q*6<;2zDqh;2A7>zp@NDohC=%T7#ezdt!aQ}nA+ViaaULgrp@wYJSMS+) z{)up3I4U~!e7HE=mb*LYhOZ1NKWa2XwqX2XFxTb>N9SdI8ygQXHwVy*1M^xpQzKR) z7^$-UzlDVoUBJjPFAgxkFBreJKL3t;P1y1Z<__g}bK@QE-qAZ+2w%b6B5{^Y^yR4u zL2rf$JO6Xq?~DY80PK1EcD^6<3^b^cZ4C;>j()rl6c81rl$6Ua&7tPr%vN-ijk7@) z|CjICFNig4;g)kzI~1_Z5YDUgZA+OyKdqM0TYX@2yb- zBUh5P+f8(=I}ynjdj;8EU85p>LPC!~G_tSyQ|p(6x1Rqvk_w-<(iZ05r#?&B6CHcj z=Ghq)&Z3}GC@#2cUum6%OSACv+b@XwrB6*^I>%2UV?Zr=OzAg4)VAtn>vyi>q{`<wPD5UuZlT7WSXsOJ(3>`kr~IJ#8jFM{T3 zXtFF#>6~_^wDj)!!ioY&me3Zr9MxR7O$t&~Zl4?KzV8!&r^_4xcefsj4ky10PfBxj zH+PmInijM!waQA;{3}zu{ke%xj%xrzM;Zx}BM?o_sEZMKOj>iMa^c?x+V8uiGxqse zD6N8ak-u>^KXr7EZbaRjlaE_lP{2P^7~OOKBW-{@_nKXh-!j_~u^jYt-gBFx;{ro| zZbxCf|NB3XZ~w9j;)4IJ?cGg~@verB@-4{`d%89(i>w}8e;?_TD<+wFJc>Q;r_Db{ zBQsUp0szcKpsn2*a$ILGF!KR3&m`P!91mH;)b}fA-&bVpgV5(p*Fzh(h1O#m;4z;L zN1cifMsL5%iHs1$ORccVr9>wX3#)x+Y5eel?y&*mKA0xt8{Js0;Lzcg{|->Yxzo07 z2jKK$-0OLvtWn2@PE)Zc>01(i=$Fb4t9&8T7iF10Qe(jM6u$j&(reC*n+qYehABPj z_ODZ@mqfO+dh7#T3@#?2Z%on%B4ysj3&kyrT!J`->;fT0R(C7S?jUMxGKz$trC}@) z+}&vKlFCNq%jA=23|u^vWp74!&=D@?LOb85*w#2N1DH{Rr$qlr|uQL^N- zQ235iHeC`+SDrxCOuD-^jQUJrZR8z;ReV zt~A_IMPSlE7?4<4n>zn=#Y?z9V=;}WBSq~!Z@I>%yF(|yQ?ur_EdA^|=~q|#M=8-% zYkME>x<7p`HwAyy-~4E76GowNiY`++c4a7N;`0rny^MW|*rObVCeS-c?Q;$4PpcsA zG~&GI2pHlE1)k*5K-x613lVMNC+Q$AvnW|aWXX4hxOKkusE3C0KMEy##QO9<{IdOm zsXhK|DXTnqWlOa)O_e>_pOV~28%6hQRv;sY7tJs9>P=0~!l$<@FxPKuFVdpFH>>h?U=OHk) zN4(@${K-t?G*gWAZu^HpI0^+$_`?&v3|wLdjKdS5z3>Mn4JidN-mQENI11QV1op2L zu0y13tatg(zbEhETrdxV9!TQWwQOMZjPfX8kNJdjL4_wt99y|&1;glY=Go1ninNOn z{_@cA?3#!(R?|)ipQcL*GyIqB0lUk=YnOR8Xujlp*KPo|?sOZ{&&mx)(dYASx$Kaf z!b8Si$t0tLyMFnx2VxyB@1jv@^o^4vP6wPLIYG5MTGZcW&`XbN+Ds}fHkvnWjFr{f zGLvRTJeoU>I)m+%@GP__0QW|`H42@P^hdI{yRO$(%N&(AkAgF|fq(48gA;6M`n}w6 z*R;E8zU>?0&iB-&AtQD9oyr7Hj~SDlYD;kC=fJBsV$(6b=#X3Nth7&^yw|-x5BMEY zt6#b9M|LTVR`)7d2pOZcpZc%Y;GsvNC$OS7(WLXJI%_l<`HZP0%R@+2GwkZ9eKFPq7CP?hlPAWjlS3NU|7c@__^T4)adNs2O%F< zEurXH`wc{d3sGa@<=5(;=VRS4Fdzv6-JiU=Wp+EqB!1Kg6QBy6dWTZx*uLSpN zYJ9Ie56YFsOak!MWaOo4(mmo+ zan4_GrCz@beE67K3Y+w*frTmUHwwD+o@oN+5gMH>!=Cv8AK~)0N{YO3 zR@TYzh_qd7qfa?7_>=laOd@d>-`wS)aX3TM*-G2UZ0Fp2;VL<2}2=3pq~A(JIPRZK{EJJFcSS&-2L7(sev*Wm z&Y4dZ%sDA9ubwZ*@2HmIQ^NE51-xBVov&r*%cd^DNb+4jT*_eg=^UeoH+TF+wTQFO z6+!maXZFrN2^qta<{fFMv)>gly7iF{b@q!3tBtYm$_@@f3`?yTb=|ZN)fvY+?$&7W zADMsrQYX_68<&sqXbi@_=v$OK8j0h{iA?*VYGo?fTYF+Zp<377N}a{ha+>>N72x{* zjAiO*`GpOYO!+j|J$a*7?WaG^;WrjUdWl;4d>o#*{G$Z1^j0+y32W(hlqvCr-e20- z;5}tW!HqM`%ZWcH_~UA#<6PI;EM(;R>4kwB7Vv-|k4`<5@v|^f+cWw4`h@Vy2^p#u zl2I>C$V$Lyn@N0pzX~W=hSEwnhE|-zHY|7V&0_zN_%FG*{#9i6x5Ab4#{A2NkzL2` zzY0R;*VXYm@18R-)R_&Z)jtQNA9?5b;F;a~n1^dta2W=tQz5E6u8xtg zr6gaqr>^;cXei8r)sz2=h4yEDQ)}$t_4M$sq6*Rc8)k-a=$DuA`OsvZ#iWZj!?@gL zSm(BA+=3Shy$`tknq5MUzeox*m98yS3(*kw;NknhaJkKK&b2Y+u%jQ+R!^U(slI2K zKO~z*I}z@360yP?)lpEc|Y7=%!hHoWVVma+?4jYxmfc(b%~eHNEmD+Kr%M2-Gbj@>D z5Cx(6D14XII2%M&q4~UehNJps{OQ&k`9>`itb46%^_}^J-=2?504-scQ~K@|3Jr?w zD&CSiT*G(unL*!MU#})PB`u7+g|M6p)N-}ruh~!4sd>9(oBs^kS&`Hl@Sy2ToYgnZ zAB*69!^Kof;PUxkeA6wEZj zYj(ulKFG&w1puB%9(uK(O~YLF_RR=R6Xyz^fQH@XSPHmm_bgCjF!0s_Q#ID5w0$Yp zxUh!_I@Bi_|0I(4`o&vMmrWWjy8-?E(kDo9qC&2(-HdRLn=cpXDf9Xo>}MK|e6RTTz z!uF<{?L@)r&>WksR0zw!qhBG<(I-}*&q{-7V<2YKammr2C zahh!tH>5srLnyh>98Hm^fLXg^xuSS8feN;f_nYd2Q^`w|=HHntcuisi#$w)g^O*L2!84njIL66#_Pi5Xk=0H1Jdib6ov@HdiM~PPx$>*qcs12sPw601 zJnSZ!R|lT_j56Am+hA*R!M02wGH_PUKyJWG0_U)Z%=2c&6o-RI~z zqy{(kz6$)4`X&u@-e&3csINYoVJk3N4l6oXMJ(W~q z@Zrp?^KiD@^4iOU#_9J)M~Fh@Q+64@>BJKTq4h9l(15ho255NC>O{!!YFh@SE!((F1jlCEr%Jq*9s%?2VxfOf)Z6~|)|98sGiOvC)4 z%InQnpuO3sGS<_>^ZtPv8wwW)=g1zTt5ahLNNOKA_+2(;+lNBNw|KYXe3CPlLsl(77k_u6sknqqO9mWw z13yO(a=3J_mkd600T$!9C@pH^8BG8EK|8#Fn{ClH& zPJ`C9t@Mh%cCt3+6aq5H75a1D4CuX|u^J14C4HWENdk0Kv`qctG+gF<@89wx{^}Lk zU5^~|j+b%GBIQ84UX*lK5^Tglawn2p<~NU5aK6H)I;i6gH|)Mc((Jz^-dv%?R1WT( zDl2?J_xt>39e+&>a!{Jdh+6Mvff8p>TA-!{vG*r%X9NCc=qa#Mt9GF&<=0IzvP?Y3 zms@Q14MtOTqjm3Ve%Wlr_AgrZ{pVeu5nq1pX!^4xJx1)|mB?`=b=vWImH*VWHc*v+ zPeXQ2H=|}a=>ELat9u#F*HzK>{7sE}nHRME^vgr*&9}1VBK`z|0gBLHF735%;Xm^- zIUG2`qM9Lk3E#Jv{aj)t7k-!R$$23k0frqc^qw`CO5n~n-|W1ErAqiJr&0Gw+6V~0|VrhM`EoOPm;NI^52FP7iK zWyjI!)Tr>z$*?I~*WCKkG*tPN->a(zbHNOI{}3<)|8DN-R9-9gsqtvW1|CbE-+Lu5njjJs5G zOte|N{k|^orB=~8&dHV`UAICiGExsatq+P+xBpYi{m(xApSr`oGo4{2?lW0qh=)ZM zELae|XzRts9@cW%ATsz}9qNg9%ca?m#D7mlYfzO`Xp0z%Z0jtw^xJc?YD)Cz&S{#@ zW^GM=yW5}q^snf2zM&@yEhH$x>SWzC*;z5traA0JzM;J7@I&L8aue&(1L@~H3*4pW zwlJ>-p21sFFa83@e5V{w84xqvnqi1;$9tqXkIRMvt^2wG5dI<9>zo_<7AS3)Z_@Yc zMJ}Mho?%Pd{8PV^|9X46?W)7CAe<4{Gdjvd=ApEc7mXOzq-J2LII zfzp4nWl??h)^;J@i-BjdO^U(x1PW4MFi^ zSOZx#sE_-P=Gstr1{h2wmd+6Es5zP-!#<+DY(Pk04w$iV{58WZDQ)fhT-rjq^Ku#V7jrUyTB0#dW<4cEtG zxQ(w0_&<$0dL_$p_&FI*T%-E#etJsts^mLozc$tsCj^P_7PXXFRe6a|ME%PrQH3BDSj_J76JK@OC&wy5cf1rvUEa~*U^!)!L&`~J*b}9CWeK= z)CI8@($Hsy@TzT`YG6mx3Jqx-I%XQopRQ0OYz%R2HJo^C5_&b*s<4KgFIdlnQ70PIMx~y^bc)>WbKWFkQG@IH4_FW*` zdSEa8Re=Q5F6dF93bw-P%je(UD6w{My|6e%Uj|0o;jW>v(jI+r#D?4NkCXHehu$z- z@OGCA{ndJuCC4iB!;qC8g5!Lk5$NMevdQc)Go9s~LB5e=aUObO+%tWXh_$=a$12P! zgZ&aIxo08xoh8^i%glPZd>8n2vL0*vbnps;YIu?p&?Q=xIj_`{ET4qM=zr_&9sIy1 z3Cn|4x{A*6Qvf6h`eEE{*t+bbi_1wh;N=}{omV^knNmC8iMvq8%OUA}Mi15`C01BB z9fzb}p&yL3O*#OCz!cWyt$4vl0E{E@vLdf}-pOc@b}V8ZCCjY~4FHI-JVOCvoUuMZs7SPdrzV=`H-XOAm4-l3(mQ5E%F;z0&9&tUPIRo zlGSW{ScU(I8)+eJ%!7G=wb8M!ZUBpJ>EVBEfATc{F9yaRt&=f zRgdfrHzxh0s3CO|O~8a_aMJAtFq|J3cUj&<=ZS)yxflX8#7OjLUaH$KeblkGw4mM|Vrqr=dQ@-XZFn)Jxg zw2p}%CmUVzbi003QM#Qe^?2AM&GpOxdFG-kD1D;|p&Sq2i^XED!IZaw5j;k-3;}v%Wo7 z9N`5kov&S$6yHAgaq!@zuld;SMj}Z&k9Ht&G?g#>Qu)_YTor6; z-rgP?`TnJv5x}9{6(lfHo|`WmshRQ!pC)?UVb0R^!7d}&tpaX!Sm5T_O(9~q+{wC! zw1Y&2@g~WaKMJG()&D)hrl7zvQm5zxE-3S zWhBDhbxJ)TTc(r~TX}EAX}vhyyHCBW4qpWGSic}l>>(@{mQm2ITHFFJ=T!@iO`x9~ zx$B566$U_vtG~cmLwW22lJbH_U%CdG`aCD#s1etb4=Rk)>e$=;ldvlI!krERugO;% zbbia3y2y~=&mcnfn(ZNC$DxYN)hQ-cTmq1X5!T%ZRwUr1#N z=_P~56f9)AA&<=KZcR8K#jVo=Ff1qQ58MQJ-bP%pOZmavL7`9(^8BaP7LzCUK-8Rq zQ!8Hn-0DDsGF#7ns)e`Ev)K5t)_nx-l-awpTDv~=agIF3k&iXxMSRUg#fTlX1BPl%|%5;bJ zw8*?_`R$kIWV1|#00gALOpaD~O^ZAmBvG_9Vg2U|fIROn#+m&&lAgOLCjgl^i>G

From 10a78e20fc2f66d91d29a7801f2329b7902cacff Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Tue, 28 Jul 2020 19:25:54 +0800 Subject: [PATCH 053/116] Tweak CI config to run on all branches and on check_suite (#94) Experimenting with CI configs to better support Stack Attack --- .github/workflows/node.js.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index c7af1ec4a7e7f..d0667a7600136 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -10,7 +10,7 @@ on: push: branches: [master] pull_request: - branches: [master] + check_suite: jobs: build: From 415dc161b3a72d0a26efa1cedc65b661ff2cd95f Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Tue, 28 Jul 2020 13:23:41 +0800 Subject: [PATCH 054/116] [Optimize flamechart][1/4] Add flamechart to ReactProfilerData This commit begins a stack of PRs that optimizes our flamechart. Broadly, we need to replace the use of Speedscope's flamechart types with our own types that are optimized for our rendering code. As flamechart was always moved around together with ReactProfilerData, it makes sense to move flamechart into it. That also necessitates moving preprocessFlamechart into preprocessData. This PR works towards #50. * `yarn flow`: errors present, but no errors in affected code. * `yarn lint` * `yarn start` --- src/App.js | 23 +++++------------------ src/CanvasPage.js | 30 ++++++------------------------ src/ImportPage.js | 17 +++-------------- src/types.js | 5 +++-- src/util/preprocessData.js | 22 ++++++++++++++++++++-- src/util/preprocessFlamechart.js | 21 --------------------- 6 files changed, 37 insertions(+), 81 deletions(-) delete mode 100644 src/util/preprocessFlamechart.js diff --git a/src/App.js b/src/App.js index 00c91728b5a95..8de8b1ad4bc77 100644 --- a/src/App.js +++ b/src/App.js @@ -1,9 +1,8 @@ // @flow -import type {FlamechartData, ReactProfilerData} from './types'; +import type {ReactProfilerData} from './types'; -import React, {useState, useCallback} from 'react'; -import {unstable_batchedUpdates} from 'react-dom'; +import React, {useState} from 'react'; import ImportPage from './ImportPage'; import CanvasPage from './CanvasPage'; @@ -12,22 +11,10 @@ export default function App() { const [profilerData, setProfilerData] = useState( null, ); - const [flamechart, setFlamechart] = useState(null); - const handleDataImported = useCallback( - ( - importedProfilerData: ReactProfilerData, - importedFlamechart: FlamechartData, - ) => { - unstable_batchedUpdates(() => { - setProfilerData(importedProfilerData); - setFlamechart(importedFlamechart); - }); - }, - ); - if (profilerData && flamechart) { - return ; + if (profilerData) { + return ; } else { - return ; + return ; } } diff --git a/src/CanvasPage.js b/src/CanvasPage.js index c89719f70398f..7767e82d19670 100644 --- a/src/CanvasPage.js +++ b/src/CanvasPage.js @@ -33,11 +33,7 @@ import {ContextMenu, ContextMenuItem, useContextMenu} from './context'; const CONTEXT_MENU_ID = 'canvas'; -import type { - FlamechartData, - ReactHoverContextInfo, - ReactProfilerData, -} from './types'; +import type {ReactHoverContextInfo, ReactProfilerData} from './types'; import {useCanvasInteraction} from './useCanvasInteraction'; import { FlamegraphView, @@ -48,28 +44,21 @@ import { type ContextMenuContextData = {| data: ReactProfilerData, - flamechart: FlamechartData, hoveredEvent: ReactHoverContextInfo | null, |}; type Props = {| profilerData: ReactProfilerData, - flamechart: FlamechartData, |}; -function CanvasPage({profilerData, flamechart}: Props) { +function CanvasPage({profilerData}: Props) { return (

{({height, width}: {height: number, width: number}) => ( - + )}
@@ -104,17 +93,11 @@ const copySummary = (data, measure) => { type AutoSizedCanvasProps = {| data: ReactProfilerData, - flamechart: FlamechartData, height: number, width: number, |}; -function AutoSizedCanvas({ - data, - flamechart, - height, - width, -}: AutoSizedCanvasProps) { +function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) { const canvasRef = useRef(null); const [isContextMenuShown, setIsContextMenuShown] = useState(false); @@ -156,7 +139,7 @@ function AutoSizedCanvas({ const flamegraphView = new FlamegraphView( surfaceRef.current, {origin: zeroPoint, size: {width, height}}, - flamechart, + data.flamechart, data, ); flamegraphViewRef.current = flamegraphView; @@ -194,7 +177,7 @@ function AutoSizedCanvas({ ); surfaceRef.current.rootView = rootViewRef.current; - }, [data, flamechart, setHoveredEvent]); + }, [data, setHoveredEvent]); useLayoutEffect(() => { if (canvasRef.current) { @@ -229,7 +212,6 @@ function AutoSizedCanvas({ useContextMenu({ data: { data, - flamechart, hoveredEvent, }, id: CONTEXT_MENU_ID, diff --git a/src/ImportPage.js b/src/ImportPage.js index e67e42733cd11..825311ac5a81a 100644 --- a/src/ImportPage.js +++ b/src/ImportPage.js @@ -1,38 +1,27 @@ // @flow import type {TimelineEvent} from '@elg/speedscope'; -import type {FlamechartData, ReactProfilerData} from './types'; +import type {ReactProfilerData} from './types'; import React, {useEffect, useCallback, useRef} from 'react'; import profilerBrowser from './assets/profilerBrowser.png'; import style from './ImportPage.css'; import preprocessData from './util/preprocessData'; -import preprocessFlamechart from './util/preprocessFlamechart'; import {readInputData} from './util/readInputData'; // TODO: Use for dev only, switch to import file after import JSON_PATH from 'url:../static/perfprofilev2.json'; type Props = {| - onDataImported: ( - profilerData: ReactProfilerData, - flamechart: FlamechartData, - ) => void, + onDataImported: (profilerData: ReactProfilerData) => void, |}; export default function ImportPage({onDataImported}: Props) { const processTimeline = useCallback( (events: TimelineEvent[]) => { - // Filter null entries and sort by timestamp. - // I would not expect to have to do either of this, - // but some of the data being passed in requires it. - events = events.filter(Boolean).sort((a, b) => (a.ts > b.ts ? 1 : -1)); - if (events.length > 0) { - const processedData = preprocessData(events); - const processedFlamechart = preprocessFlamechart(events); - onDataImported(processedData, processedFlamechart); + onDataImported(preprocessData(events)); } }, [onDataImported], diff --git a/src/types.js b/src/types.js index 4a52abef29686..5d01111361201 100644 --- a/src/types.js +++ b/src/types.js @@ -87,11 +87,14 @@ export type ReactMeasure = {| +depth: number, |}; +export type FlamechartData = Flamechart; + export type ReactProfilerData = {| startTime: number, duration: number, events: ReactEvent[], measures: ReactMeasure[], + flamechart: FlamechartData, |}; export type ReactHoverContextInfo = {| @@ -100,5 +103,3 @@ export type ReactHoverContextInfo = {| data: $ReadOnly | null, flamechartNode: FlamechartFrame | null, |}; - -export type FlamechartData = Flamechart; diff --git a/src/util/preprocessData.js b/src/util/preprocessData.js index 0c28c1db8980d..fd2119db911a0 100644 --- a/src/util/preprocessData.js +++ b/src/util/preprocessData.js @@ -1,9 +1,11 @@ // @flow +import {importFromChromeTimeline, Flamechart} from '@elg/speedscope'; import type {TimelineEvent} from '@elg/speedscope'; import type { Milliseconds, BatchUID, + FlamechartData, ReactLane, ReactMeasureType, ReactProfilerData, @@ -345,18 +347,34 @@ function processTimelineEvent( } } +function preprocessFlamechart(rawData: TimelineEvent[]): FlamechartData { + const parsedData = importFromChromeTimeline(rawData, 'react-devtools'); + const profile = parsedData.profiles[0]; // TODO: Choose the main CPU thread only + const flamechart = new Flamechart({ + getTotalWeight: profile.getTotalWeight.bind(profile), + forEachCall: profile.forEachCall.bind(profile), + formatValue: profile.formatValue.bind(profile), + getColorBucketForFrame: () => 0, + }); + return flamechart; +} + export default function preprocessData( timeline: TimelineEvent[], ): ReactProfilerData { - const profilerData = { + const flamechart = preprocessFlamechart(timeline); + + const profilerData: ReactProfilerData = { startTime: 0, duration: 0, events: [], measures: [], + flamechart, }; - // TODO: Sort `timeline`. JSON Array Format trace events need not be ordered. See: + // Sort `timeline`. JSON Array Format trace events need not be ordered. See: // https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview#heading=h.f2f0yd51wi15 + timeline = timeline.filter(Boolean).sort((a, b) => (a.ts > b.ts ? 1 : -1)); // Events displayed in flamechart have timestamps relative to the profile // event's startTime. Source: https://github.com/v8/v8/blob/44bd8fd7/src/inspector/js_protocol.json#L1486 diff --git a/src/util/preprocessFlamechart.js b/src/util/preprocessFlamechart.js deleted file mode 100644 index dc99185115896..0000000000000 --- a/src/util/preprocessFlamechart.js +++ /dev/null @@ -1,21 +0,0 @@ -// @flow - -import {importFromChromeTimeline, Flamechart} from '@elg/speedscope'; - -import type {TimelineEvent} from '@elg/speedscope'; -import type {FlamechartData} from '../types'; - -export default function preprocessFlamechart( - rawData: TimelineEvent[], -): FlamechartData { - const parsedData = importFromChromeTimeline(rawData, 'react-devtools'); - const profile = parsedData.profiles[0]; // TODO Choose the main CPU thread only - const flamechart = new Flamechart({ - getTotalWeight: profile.getTotalWeight.bind(profile), - forEachCall: profile.forEachCall.bind(profile), - formatValue: profile.formatValue.bind(profile), - getColorBucketForFrame: () => null, - }); - - return flamechart; -} From 26b62b940ff863be4bde3e350d32d2e973a1b1d0 Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Wed, 29 Jul 2020 14:39:37 +0800 Subject: [PATCH 055/116] Fix tests (#97) --- .babelrc | 8 ------- babel.config.js | 5 ++++ jest.config.js | 4 ++++ .../__snapshots__/preprocessData-test.js.snap | 22 +++++++++++++++++ src/util/__tests__/preprocessData-test.js | 24 +++++++------------ 5 files changed, 39 insertions(+), 24 deletions(-) delete mode 100644 .babelrc create mode 100644 babel.config.js diff --git a/.babelrc b/.babelrc deleted file mode 100644 index aa1bd21c2b638..0000000000000 --- a/.babelrc +++ /dev/null @@ -1,8 +0,0 @@ -{ - "presets": [ - [ - "react-app", - { "absoluteRuntime": false, "flow": true, "typescript": false } - ] - ] -} diff --git a/babel.config.js b/babel.config.js new file mode 100644 index 0000000000000..6640bf9eda5e3 --- /dev/null +++ b/babel.config.js @@ -0,0 +1,5 @@ +module.exports = { + presets: [ + ['react-app', {absoluteRuntime: false, flow: true, typescript: false}], + ], +}; diff --git a/jest.config.js b/jest.config.js index 30e44cbe58974..4f08d903d3b99 100644 --- a/jest.config.js +++ b/jest.config.js @@ -2,4 +2,8 @@ module.exports = { moduleNameMapper: { '\\.css$': 'identity-obj-proxy', }, + transformIgnorePatterns: [ + // Pass @elg/speedscope through transforms + '/node_modules/(?!@elg/speedscope).+\\.js$', + ], }; diff --git a/src/util/__tests__/__snapshots__/preprocessData-test.js.snap b/src/util/__tests__/__snapshots__/preprocessData-test.js.snap index 411d547729275..0546645575e4b 100644 --- a/src/util/__tests__/__snapshots__/preprocessData-test.js.snap +++ b/src/util/__tests__/__snapshots__/preprocessData-test.js.snap @@ -573,6 +573,17 @@ Object { "type": "suspense-resolved", }, ], + "flamechart": Flamechart { + "layers": Array [], + "minFrameWidth": 1, + "source": Object { + "forEachCall": [Function], + "formatValue": [Function], + "getColorBucketForFrame": [Function], + "getTotalWeight": [Function], + }, + "totalWeight": -8993778496, + }, "measures": Array [ Object { "batchUID": 0, @@ -1276,6 +1287,17 @@ Object { "type": "schedule-force-update", }, ], + "flamechart": Flamechart { + "layers": Array [], + "minFrameWidth": 1, + "source": Object { + "forEachCall": [Function], + "formatValue": [Function], + "getColorBucketForFrame": [Function], + "getTotalWeight": [Function], + }, + "totalWeight": -40806924876, + }, "measures": Array [ Object { "batchUID": 0, diff --git a/src/util/__tests__/preprocessData-test.js b/src/util/__tests__/preprocessData-test.js index aee183c1b791c..30e5481bb7e22 100644 --- a/src/util/__tests__/preprocessData-test.js +++ b/src/util/__tests__/preprocessData-test.js @@ -50,27 +50,17 @@ describe(getLanesFromTransportDecimalBitmask, () => { }); describe(preprocessData, () => { - it('should return empty data given an empty timeline', () => { - expect(preprocessData([])).toEqual({ - startTime: 0, - duration: 0, - events: [], - measures: [], - }); + it('should throw given an empty timeline', () => { + expect(() => preprocessData([])).toThrow(); }); - it('should return empty data given a timeline with no Profile event', () => { - expect( + it('should throw given a timeline with no Profile event', () => { + expect(() => // prettier-ignore preprocessData([ {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--schedule-render-512-","ph":"R","pid":9312,"tid":10252,"ts":8994056569,"tts":1816966}, ]), - ).toEqual({ - startTime: 0, - duration: 0, - events: [], - measures: [], - }); + ).toThrow(); }); it('should return empty data given a timeline with no React scheduling profiling marks', () => { @@ -85,11 +75,13 @@ describe(preprocessData, () => { {"pid":57632,"tid":38659,"ts":874860756224,"ph":"X","cat":"disabled-by-default-devtools.timeline","name":"RunTask","dur":7,"tdur":6,"tts":8700285008,"args":{}}, {"pid":57632,"tid":38659,"ts":874860756233,"ph":"X","cat":"disabled-by-default-devtools.timeline","name":"RunTask","dur":5,"tdur":4,"tts":8700285017,"args":{}}, ]), - ).toEqual({ + ).toMatchObject({ startTime: 8993778496, duration: 865866977.737, events: [], measures: [], + // TODO: Change expectation back to toEqual and test for empty flamechart + // when custom flamechart type is added. }); }); From 1f46ef2243b950fc6e5a6555c633610edc5d0373 Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Tue, 28 Jul 2020 14:22:39 +0800 Subject: [PATCH 056/116] [Optimize flamechart][2/4] Replace Speedscope types with custom stack frame type Lays groundwork for #75 by reducing the flamechart data passed around the app. Was also intended to help #50 by moving some division operations from the hot render loops into preprocessFlamechart, but any performance gains are negligible. * `yarn flow`: no errors in modified code * `yarn lint` * `yarn start`: no performance difference --- src/CanvasPage.js | 34 +++++++---- src/EventTooltip.js | 34 ++++++----- src/canvas/views/FlamegraphView.js | 59 +++++++++---------- src/types.js | 26 ++++++-- .../__snapshots__/preprocessData-test.js.snap | 24 +------- src/util/__tests__/preprocessData-test.js | 7 ++- src/util/preprocessData.js | 24 ++++++-- 7 files changed, 116 insertions(+), 92 deletions(-) diff --git a/src/CanvasPage.js b/src/CanvasPage.js index 7767e82d19670..bac804d81482e 100644 --- a/src/CanvasPage.js +++ b/src/CanvasPage.js @@ -191,7 +191,7 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) { hoveredEvent && (hoveredEvent.event || hoveredEvent.measure || - hoveredEvent.flamechartNode) + hoveredEvent.flamechartStackFrame) ) { setMouseLocation({ x: interaction.payload.event.x, @@ -226,7 +226,7 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) { if (!hoveredEvent || hoveredEvent.event !== event) { setHoveredEvent({ event, - flamechartNode: null, + flamechartStackFrame: null, measure: null, data, }); @@ -240,7 +240,7 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) { if (!hoveredEvent || hoveredEvent.measure !== measure) { setHoveredEvent({ event: null, - flamechartNode: null, + flamechartStackFrame: null, measure, data, }); @@ -250,11 +250,14 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) { const {current: flamegraphView} = flamegraphViewRef; if (flamegraphView) { - flamegraphView.onHover = flamechartNode => { - if (!hoveredEvent || hoveredEvent.flamechartNode !== flamechartNode) { + flamegraphView.onHover = flamechartStackFrame => { + if ( + !hoveredEvent || + hoveredEvent.flamechartStackFrame !== flamechartStackFrame + ) { setHoveredEvent({ event: null, - flamechartNode, + flamechartStackFrame, measure: null, data, }); @@ -285,7 +288,7 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) { const {current: flamegraphView} = flamegraphViewRef; if (flamegraphView) { flamegraphView.setHoveredFlamechartNode( - hoveredEvent ? hoveredEvent.flamechartNode : null, + hoveredEvent ? hoveredEvent.flamechartStackFrame : null, ); } }, [ @@ -311,7 +314,11 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) { if (contextData.hoveredEvent == null) { return null; } - const {event, flamechartNode, measure} = contextData.hoveredEvent; + const { + event, + flamechartStackFrame, + measure, + } = contextData.hoveredEvent; return ( {event !== null && ( @@ -342,19 +349,20 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) { Copy summary )} - {flamechartNode !== null && ( + {flamechartStackFrame !== null && ( copy(flamechartNode.node.frame.file)} + onClick={() => copy(flamechartStackFrame.scriptUrl)} title="Copy file path"> Copy file path )} - {flamechartNode !== null && ( + {flamechartStackFrame !== null && ( copy( - `line ${flamechartNode.node.frame.line || - ''}, column ${flamechartNode.node.frame.col || ''}`, + `line ${flamechartStackFrame.locationLine || + ''}, column ${flamechartStackFrame.locationColumn || + ''}`, ) } title="Copy location"> diff --git a/src/EventTooltip.js b/src/EventTooltip.js index 3ab48ac4474db..300e4039f192c 100644 --- a/src/EventTooltip.js +++ b/src/EventTooltip.js @@ -1,8 +1,8 @@ // @flow import type {Point} from './layout'; -import type {FlamechartFrame} from '@elg/speedscope'; import type { + FlamechartStackFrame, ReactEvent, ReactMeasure, ReactProfilerData, @@ -48,7 +48,7 @@ export default function EventTooltip({data, hoveredEvent, origin}: Props) { return null; } - const {event, flamechartNode, measure} = hoveredEvent; + const {event, flamechartStackFrame, measure} = hoveredEvent; if (event !== null) { switch (event.type) { @@ -107,10 +107,10 @@ export default function EventTooltip({data, hoveredEvent, origin}: Props) { console.warn(`Unexpected measure type "${measure.type}"`); break; } - } else if (flamechartNode !== null) { + } else if (flamechartStackFrame !== null) { return ( ); @@ -129,14 +129,20 @@ function formatComponentStack(componentStack: string): string { } const TooltipFlamechartNode = ({ - flamechartNode, + stackFrame, tooltipRef, }: { - flamechartNode: FlamechartFrame, + stackFrame: FlamechartStackFrame, tooltipRef: Return, }) => { - const {end, node, start} = flamechartNode; - const {col, file, line, name} = node.frame; + const { + name, + timestamp, + duration, + scriptUrl, + locationLine, + locationColumn, + } = stackFrame; return (
- {formatDuration((end - start) / 1000)} {trimComponentName(name)} + {formatDuration(duration)} {trimComponentName(name)}
Timestamp:
-
{formatTimestamp(start / 1000)}
- {file && ( +
{formatTimestamp(timestamp)}
+ {scriptUrl && ( <>
Script URL:
-
{file}
+
{scriptUrl}
)} - {(line !== undefined || col !== undefined) && ( + {(locationLine !== undefined || locationColumn !== undefined) && ( <>
Location:
- line {line}, column {col} + line {locationLine}, column {locationColumn}
)} diff --git a/src/canvas/views/FlamegraphView.js b/src/canvas/views/FlamegraphView.js index 603bc1b40adb2..a8fdb8f880301 100644 --- a/src/canvas/views/FlamegraphView.js +++ b/src/canvas/views/FlamegraphView.js @@ -1,8 +1,11 @@ // @flow -import type {FlamechartFrame} from '@elg/speedscope'; import type {Interaction, HoverInteraction} from '../../useCanvasInteraction'; -import type {FlamechartData, ReactProfilerData} from '../../types'; +import type { + Flamechart, + FlamechartStackFrame, + ReactProfilerData, +} from '../../types'; import type {Rect, Size} from '../../layout'; import { @@ -28,17 +31,17 @@ import { } from '../constants'; export class FlamegraphView extends View { - flamechart: FlamechartData; + flamechart: Flamechart; profilerData: ReactProfilerData; intrinsicSize: Size; - hoveredFlamechartNode: FlamechartFrame | null = null; - onHover: ((node: FlamechartFrame | null) => void) | null = null; + hoveredStackFrame: FlamechartStackFrame | null = null; + onHover: ((node: FlamechartStackFrame | null) => void) | null = null; constructor( surface: Surface, frame: Rect, - flamechart: FlamechartData, + flamechart: Flamechart, profilerData: ReactProfilerData, ) { super(surface, frame); @@ -46,7 +49,7 @@ export class FlamegraphView extends View { this.profilerData = profilerData; this.intrinsicSize = { width: this.profilerData.duration, - height: this.flamechart.getLayers().length * FLAMECHART_FRAME_HEIGHT, + height: this.flamechart.length * FLAMECHART_FRAME_HEIGHT, }; } @@ -54,11 +57,11 @@ export class FlamegraphView extends View { return this.intrinsicSize; } - setHoveredFlamechartNode(hoveredFlamechartNode: FlamechartFrame | null) { - if (this.hoveredFlamechartNode === hoveredFlamechartNode) { + setHoveredFlamechartNode(hoveredStackFrame: FlamechartStackFrame | null) { + if (this.hoveredStackFrame === hoveredStackFrame) { return; } - this.hoveredFlamechartNode = hoveredFlamechartNode; + this.hoveredStackFrame = hoveredStackFrame; this.setNeedsDisplay(); } @@ -66,7 +69,7 @@ export class FlamegraphView extends View { const { frame, flamechart, - hoveredFlamechartNode, + hoveredStackFrame: hoveredFlamechartNode, intrinsicSize, visibleArea, } = this; @@ -85,8 +88,8 @@ export class FlamegraphView extends View { const scaleFactor = positioningScaleFactor(intrinsicSize.width, frame); - for (let i = 0; i < flamechart.getLayers().length; i++) { - const nodes = flamechart.getLayers()[i]; + for (let i = 0; i < flamechart.length; i++) { + const stackLayer = flamechart[i]; const layerY = Math.floor(frame.origin.y + i * FLAMECHART_FRAME_HEIGHT); if ( @@ -96,17 +99,16 @@ export class FlamegraphView extends View { continue; // Not in view } - for (let j = 0; j < nodes.length; j++) { - const {end, node, start} = nodes[j]; - const {name} = node.frame; + for (let j = 0; j < stackLayer.length; j++) { + const {name, timestamp, duration} = stackLayer[j]; - const width = durationToWidth((end - start) / 1000, scaleFactor); + const width = durationToWidth(duration, scaleFactor); if (width < 1) { continue; // Too small to render at this zoom level } const x = Math.floor( - timestampToPosition(start / 1000, scaleFactor, frame), + timestampToPosition(timestamp, scaleFactor, frame), ); const nodeRect: Rect = { origin: {x, y: layerY}, @@ -121,7 +123,7 @@ export class FlamegraphView extends View { continue; // Not in view } - const showHoverHighlight = hoveredFlamechartNode === nodes[j]; + const showHoverHighlight = hoveredFlamechartNode === stackLayer[j]; context.fillStyle = showHoverHighlight ? COLORS.FLAME_GRAPH_HOVER : COLORS.FLAME_GRAPH; @@ -195,11 +197,11 @@ export class FlamegraphView extends View { const layerIndex = Math.floor( adjustedCanvasMouseY / FLAMECHART_FRAME_HEIGHT, ); - if (layerIndex < 0 || layerIndex >= flamechart.getLayers().length) { + if (layerIndex < 0 || layerIndex >= flamechart.length) { onHover(null); return; } - const layer = flamechart.getLayers()[layerIndex]; + const layer = flamechart[layerIndex]; if (!layer) { return null; @@ -211,18 +213,13 @@ export class FlamegraphView extends View { let stopIndex = layer.length - 1; while (startIndex <= stopIndex) { const currentIndex = Math.floor((startIndex + stopIndex) / 2); - const flamechartNode = layer[currentIndex]; - - const {end, start} = flamechartNode; - - const width = durationToWidth((end - start) / 1000, scaleFactor); - - const x = Math.floor( - timestampToPosition(start / 1000, scaleFactor, frame), - ); + const flamechartStackFrame = layer[currentIndex]; + const {timestamp, duration} = flamechartStackFrame; + const width = durationToWidth(duration, scaleFactor); + const x = Math.floor(timestampToPosition(timestamp, scaleFactor, frame)); if (x <= location.x && x + width >= location.x) { - onHover(flamechartNode); + onHover(flamechartStackFrame); return; } diff --git a/src/types.js b/src/types.js index 5d01111361201..05c72016f0f40 100644 --- a/src/types.js +++ b/src/types.js @@ -1,7 +1,5 @@ // @flow -import type {Flamechart, FlamechartFrame} from '@elg/speedscope'; - // Type utilities // Source: https://github.com/facebook/flow/issues/4002#issuecomment-323612798 @@ -87,19 +85,37 @@ export type ReactMeasure = {| +depth: number, |}; -export type FlamechartData = Flamechart; +/** + * A flamechart stack frame belonging to a stack trace. + */ +export type FlamechartStackFrame = {| + name: string, + timestamp: Milliseconds, + duration: Milliseconds, + scriptUrl?: string, + locationLine?: number, + locationColumn?: number, +|}; + +/** + * A "layer" of stack frames in the profiler UI, i.e. all stack frames of the + * same depth across all stack traces. Displayed as a flamechart row in the UI. + */ +export type FlamechartStackLayer = FlamechartStackFrame[]; + +export type Flamechart = FlamechartStackLayer[]; export type ReactProfilerData = {| startTime: number, duration: number, events: ReactEvent[], measures: ReactMeasure[], - flamechart: FlamechartData, + flamechart: Flamechart, |}; export type ReactHoverContextInfo = {| event: ReactEvent | null, measure: ReactMeasure | null, data: $ReadOnly | null, - flamechartNode: FlamechartFrame | null, + flamechartStackFrame: FlamechartStackFrame | null, |}; diff --git a/src/util/__tests__/__snapshots__/preprocessData-test.js.snap b/src/util/__tests__/__snapshots__/preprocessData-test.js.snap index 0546645575e4b..89993c69a8a0b 100644 --- a/src/util/__tests__/__snapshots__/preprocessData-test.js.snap +++ b/src/util/__tests__/__snapshots__/preprocessData-test.js.snap @@ -573,17 +573,7 @@ Object { "type": "suspense-resolved", }, ], - "flamechart": Flamechart { - "layers": Array [], - "minFrameWidth": 1, - "source": Object { - "forEachCall": [Function], - "formatValue": [Function], - "getColorBucketForFrame": [Function], - "getTotalWeight": [Function], - }, - "totalWeight": -8993778496, - }, + "flamechart": Array [], "measures": Array [ Object { "batchUID": 0, @@ -1287,17 +1277,7 @@ Object { "type": "schedule-force-update", }, ], - "flamechart": Flamechart { - "layers": Array [], - "minFrameWidth": 1, - "source": Object { - "forEachCall": [Function], - "formatValue": [Function], - "getColorBucketForFrame": [Function], - "getTotalWeight": [Function], - }, - "totalWeight": -40806924876, - }, + "flamechart": Array [], "measures": Array [ Object { "batchUID": 0, diff --git a/src/util/__tests__/preprocessData-test.js b/src/util/__tests__/preprocessData-test.js index 30e5481bb7e22..e4a3ebac12c85 100644 --- a/src/util/__tests__/preprocessData-test.js +++ b/src/util/__tests__/preprocessData-test.js @@ -75,13 +75,12 @@ describe(preprocessData, () => { {"pid":57632,"tid":38659,"ts":874860756224,"ph":"X","cat":"disabled-by-default-devtools.timeline","name":"RunTask","dur":7,"tdur":6,"tts":8700285008,"args":{}}, {"pid":57632,"tid":38659,"ts":874860756233,"ph":"X","cat":"disabled-by-default-devtools.timeline","name":"RunTask","dur":5,"tdur":4,"tts":8700285017,"args":{}}, ]), - ).toMatchObject({ + ).toEqual({ startTime: 8993778496, duration: 865866977.737, events: [], measures: [], - // TODO: Change expectation back to toEqual and test for empty flamechart - // when custom flamechart type is added. + flamechart: [], }); }); @@ -325,4 +324,6 @@ describe(preprocessData, () => { ]), ).toMatchSnapshot(); }); + + // TODO: Add test for flamechart parsing }); diff --git a/src/util/preprocessData.js b/src/util/preprocessData.js index fd2119db911a0..3cfc126212a9e 100644 --- a/src/util/preprocessData.js +++ b/src/util/preprocessData.js @@ -1,11 +1,14 @@ // @flow -import {importFromChromeTimeline, Flamechart} from '@elg/speedscope'; +import { + importFromChromeTimeline, + Flamechart as SpeedscopeFlamechart, +} from '@elg/speedscope'; import type {TimelineEvent} from '@elg/speedscope'; import type { Milliseconds, BatchUID, - FlamechartData, + Flamechart, ReactLane, ReactMeasureType, ReactProfilerData, @@ -347,15 +350,28 @@ function processTimelineEvent( } } -function preprocessFlamechart(rawData: TimelineEvent[]): FlamechartData { +function preprocessFlamechart(rawData: TimelineEvent[]): Flamechart { const parsedData = importFromChromeTimeline(rawData, 'react-devtools'); const profile = parsedData.profiles[0]; // TODO: Choose the main CPU thread only - const flamechart = new Flamechart({ + + const speedscopeFlamechart = new SpeedscopeFlamechart({ getTotalWeight: profile.getTotalWeight.bind(profile), forEachCall: profile.forEachCall.bind(profile), formatValue: profile.formatValue.bind(profile), getColorBucketForFrame: () => 0, }); + + const flamechart: Flamechart = speedscopeFlamechart.getLayers().map(layer => + layer.map(({start, end, node: {frame: {name, file, line, col}}}) => ({ + name, + timestamp: start / 1000, + duration: (end - start) / 1000, + scriptUrl: file, + locationLine: line, + locationColumn: col, + })), + ); + return flamechart; } From 036e4c0cfdf82917359dbdb602322d1542a19918 Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Tue, 28 Jul 2020 14:33:11 +0800 Subject: [PATCH 057/116] [Optimize flamechart][3/4] Rename flame graph -> flame chart --- src/CanvasPage.js | 34 +++++++++---------- src/canvas/canvasUtils.js | 8 ++--- src/canvas/constants.js | 4 +-- .../{FlamegraphView.js => FlamechartView.js} | 10 +++--- src/canvas/views/index.js | 2 +- 5 files changed, 29 insertions(+), 29 deletions(-) rename src/canvas/views/{FlamegraphView.js => FlamechartView.js} (97%) diff --git a/src/CanvasPage.js b/src/CanvasPage.js index bac804d81482e..211400fa67571 100644 --- a/src/CanvasPage.js +++ b/src/CanvasPage.js @@ -36,7 +36,7 @@ const CONTEXT_MENU_ID = 'canvas'; import type {ReactHoverContextInfo, ReactProfilerData} from './types'; import {useCanvasInteraction} from './useCanvasInteraction'; import { - FlamegraphView, + FlamechartView, ReactEventsView, ReactMeasuresView, TimeAxisMarkersView, @@ -108,7 +108,7 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) { ] = useState(null); const surfaceRef = useRef(new Surface()); - const flamegraphViewRef = useRef(null); + const flamechartViewRef = useRef(null); const axisMarkersViewRef = useRef(null); const reactEventsViewRef = useRef(null); const reactMeasuresViewRef = useRef(null); @@ -136,18 +136,18 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) { ); reactMeasuresViewRef.current = reactMeasuresView; - const flamegraphView = new FlamegraphView( + const flamechartView = new FlamechartView( surfaceRef.current, {origin: zeroPoint, size: {width, height}}, data.flamechart, data, ); - flamegraphViewRef.current = flamegraphView; - const flamegraphVScrollWrapper = new VerticalScrollView( + flamechartViewRef.current = flamechartView; + const flamechartVScrollWrapper = new VerticalScrollView( surfaceRef.current, {origin: zeroPoint, size: {width, height}}, - flamegraphView, - flamegraphView.intrinsicSize.height, + flamechartView, + flamechartView.intrinsicSize.height, ); const stackedZoomables = new StaticLayoutView( @@ -158,7 +158,7 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) { axisMarkersView, reactEventsView, reactMeasuresView, - flamegraphVScrollWrapper, + flamechartVScrollWrapper, ], ); @@ -166,7 +166,7 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) { surfaceRef.current, {origin: zeroPoint, size: {width, height}}, stackedZoomables, - flamegraphView.intrinsicSize.width, + flamechartView.intrinsicSize.width, ); rootViewRef.current = new StaticLayoutView( @@ -248,9 +248,9 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) { }; } - const {current: flamegraphView} = flamegraphViewRef; - if (flamegraphView) { - flamegraphView.onHover = flamechartStackFrame => { + const {current: flamechartView} = flamechartViewRef; + if (flamechartView) { + flamechartView.onHover = flamechartStackFrame => { if ( !hoveredEvent || hoveredEvent.flamechartStackFrame !== flamechartStackFrame @@ -267,7 +267,7 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) { }, [ reactEventsViewRef, reactMeasuresViewRef, - flamegraphViewRef, + flamechartViewRef, hoveredEvent, setHoveredEvent, ]); @@ -285,16 +285,16 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) { ); } - const {current: flamegraphView} = flamegraphViewRef; - if (flamegraphView) { - flamegraphView.setHoveredFlamechartNode( + const {current: flamechartView} = flamechartViewRef; + if (flamechartView) { + flamechartView.setHoveredFlamechartNode( hoveredEvent ? hoveredEvent.flamechartStackFrame : null, ); } }, [ reactEventsViewRef, reactMeasuresViewRef, - flamegraphViewRef, + flamechartViewRef, hoveredEvent, ]); diff --git a/src/canvas/canvasUtils.js b/src/canvas/canvasUtils.js index 96508a61f423f..f2dc6e9c669c7 100644 --- a/src/canvas/canvasUtils.js +++ b/src/canvas/canvasUtils.js @@ -49,8 +49,8 @@ export function getTimeTickInterval(zoomLevel: number) { return interval; } -const cachedFlamegraphTextWidths = new Map(); -export const trimFlamegraphText = ( +const cachedFlamechartTextWidths = new Map(); +export const trimFlamechartText = ( context: CanvasRenderingContext2D, text: string, width: number, @@ -58,10 +58,10 @@ export const trimFlamegraphText = ( for (let i = text.length - 1; i >= 0; i--) { const trimmedText = i === text.length - 1 ? text : text.substr(0, i) + '…'; - let measuredWidth = cachedFlamegraphTextWidths.get(trimmedText); + let measuredWidth = cachedFlamechartTextWidths.get(trimmedText); if (measuredWidth == null) { measuredWidth = context.measureText(trimmedText).width; - cachedFlamegraphTextWidths.set(trimmedText, measuredWidth); + cachedFlamechartTextWidths.set(trimmedText, measuredWidth); } if (measuredWidth <= width) { diff --git a/src/canvas/constants.js b/src/canvas/constants.js index 7aaebf9f84428..b510af7cc168b 100644 --- a/src/canvas/constants.js +++ b/src/canvas/constants.js @@ -61,8 +61,8 @@ export const EVENT_ROW_HEIGHT_FIXED = export const COLORS = Object.freeze({ BACKGROUND: '#ffffff', - FLAME_GRAPH: '#fff79f', - FLAME_GRAPH_HOVER: '#ffe900', + FLAME_CHART: '#fff79f', + FLAME_CHART_HOVER: '#ffe900', OTHER_SCRIPT: '#fff791', OTHER_SCRIPT_HOVER: '#ffea00', PRIORITY_BACKGROUND: '#ededf0', diff --git a/src/canvas/views/FlamegraphView.js b/src/canvas/views/FlamechartView.js similarity index 97% rename from src/canvas/views/FlamegraphView.js rename to src/canvas/views/FlamechartView.js index a8fdb8f880301..2ae144ea38256 100644 --- a/src/canvas/views/FlamegraphView.js +++ b/src/canvas/views/FlamechartView.js @@ -20,7 +20,7 @@ import { durationToWidth, positioningScaleFactor, timestampToPosition, - trimFlamegraphText, + trimFlamechartText, } from '../canvasUtils'; import { COLORS, @@ -30,7 +30,7 @@ import { REACT_WORK_BORDER_SIZE, } from '../constants'; -export class FlamegraphView extends View { +export class FlamechartView extends View { flamechart: Flamechart; profilerData: ReactProfilerData; intrinsicSize: Size; @@ -125,8 +125,8 @@ export class FlamegraphView extends View { const showHoverHighlight = hoveredFlamechartNode === stackLayer[j]; context.fillStyle = showHoverHighlight - ? COLORS.FLAME_GRAPH_HOVER - : COLORS.FLAME_GRAPH; + ? COLORS.FLAME_CHART_HOVER + : COLORS.FLAME_CHART; const drawableRect = rectIntersectionWithRect(nodeRect, visibleArea); context.fillRect( @@ -137,7 +137,7 @@ export class FlamegraphView extends View { ); if (width > FLAMECHART_TEXT_PADDING * 2) { - const trimmedName = trimFlamegraphText( + const trimmedName = trimFlamechartText( context, name, width - FLAMECHART_TEXT_PADDING * 2 + (x < 0 ? x : 0), diff --git a/src/canvas/views/index.js b/src/canvas/views/index.js index 04dfba8a12a9e..306e396f2f834 100644 --- a/src/canvas/views/index.js +++ b/src/canvas/views/index.js @@ -1,6 +1,6 @@ // @flow -export * from './FlamegraphView'; +export * from './FlamechartView'; export * from './ReactEventsView'; export * from './ReactMeasuresView'; export * from './TimeAxisMarkersView'; From 2797f85b8d68d280681355e0b5f892b73866ad31 Mon Sep 17 00:00:00 2001 From: Kartik Choudhary Date: Wed, 29 Jul 2020 15:53:34 +0000 Subject: [PATCH 058/116] Fix strict mode error (#98) --- src/ImportPage.css | 2 ++ src/ImportPage.js | 32 ++++++++++++++++---------------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/ImportPage.css b/src/ImportPage.css index bf55d3fa7d7db..dce625045e0cf 100644 --- a/src/ImportPage.css +++ b/src/ImportPage.css @@ -43,6 +43,8 @@ kbd { .legendKey { font-size: calc(8px + 1.5vmin); + margin: 0; + margin-bottom: 1rem; } .legendKey > svg { diff --git a/src/ImportPage.js b/src/ImportPage.js index 825311ac5a81a..23be7afadee4e 100644 --- a/src/ImportPage.js +++ b/src/ImportPage.js @@ -72,22 +72,22 @@ export default function ImportPage({onDataImported}: Props) {
To zoom, scroll while holding down Ctrl or{' '} Shift -

- - - - State Update Scheduled -
- - - - State Update Scheduled -
- - - - Suspended -

+

+

+ + + + State Update Scheduled +
+ + + + State Update Scheduled +
+ + + + Suspended

From fe433c82581c1eea98c32c1a9148224aec2ba9ee Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Tue, 28 Jul 2020 17:42:55 +0800 Subject: [PATCH 059/116] [Optimize flamechart][4/4] Split FlamechartView into row views Allow the view system to render only affected flamechart rows. This greatly improves flamechart hover performance, which has a high impact on our app's performance as the flamechart is the slowest view to render. Also adds a new `ColorView` view that fills the flamechart area with a solid background color to fix these issues: 1. Black empty areas appearing below flamecharts without much stack depth 2. Lines appearing between flamechart rows. My hypothesis is that these are appearing due to subpixel rendering, even though the flamechart rows' `visibleArea`s are all integers. Related to #50. * `yarn flow`: no errors in changed code * `yarn lint` * `yarn start`: 60 FPS hovers on our Facebook.com profile * `yarn test` --- src/CanvasPage.js | 11 +- src/canvas/views/FlamechartView.js | 328 +++++++++++++++++++---------- src/layout/ColorView.js | 29 +++ src/layout/StaticLayoutView.js | 6 +- src/layout/VerticalScrollView.js | 12 +- src/layout/index.js | 1 + 6 files changed, 264 insertions(+), 123 deletions(-) create mode 100644 src/layout/ColorView.js diff --git a/src/CanvasPage.js b/src/CanvasPage.js index 211400fa67571..3d021aedd6ffb 100644 --- a/src/CanvasPage.js +++ b/src/CanvasPage.js @@ -140,14 +140,13 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) { surfaceRef.current, {origin: zeroPoint, size: {width, height}}, data.flamechart, - data, + data.duration, ); flamechartViewRef.current = flamechartView; const flamechartVScrollWrapper = new VerticalScrollView( surfaceRef.current, {origin: zeroPoint, size: {width, height}}, flamechartView, - flamechartView.intrinsicSize.height, ); const stackedZoomables = new StaticLayoutView( @@ -166,7 +165,7 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) { surfaceRef.current, {origin: zeroPoint, size: {width, height}}, stackedZoomables, - flamechartView.intrinsicSize.width, + reactEventsView.intrinsicSize.width, ); rootViewRef.current = new StaticLayoutView( @@ -250,7 +249,7 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) { const {current: flamechartView} = flamechartViewRef; if (flamechartView) { - flamechartView.onHover = flamechartStackFrame => { + flamechartView.setOnHover(flamechartStackFrame => { if ( !hoveredEvent || hoveredEvent.flamechartStackFrame !== flamechartStackFrame @@ -262,7 +261,7 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) { data, }); } - }; + }); } }, [ reactEventsViewRef, @@ -287,7 +286,7 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) { const {current: flamechartView} = flamechartViewRef; if (flamechartView) { - flamechartView.setHoveredFlamechartNode( + flamechartView.setHoveredFlamechartStackFrame( hoveredEvent ? hoveredEvent.flamechartStackFrame : null, ); } diff --git a/src/canvas/views/FlamechartView.js b/src/canvas/views/FlamechartView.js index 2ae144ea38256..a6e0c0a340275 100644 --- a/src/canvas/views/FlamechartView.js +++ b/src/canvas/views/FlamechartView.js @@ -4,17 +4,21 @@ import type {Interaction, HoverInteraction} from '../../useCanvasInteraction'; import type { Flamechart, FlamechartStackFrame, - ReactProfilerData, + FlamechartStackLayer, } from '../../types'; import type {Rect, Size} from '../../layout'; import { + ColorView, View, Surface, + StaticLayoutView, rectContainsPoint, rectEqualToRect, rectIntersectsRect, rectIntersectionWithRect, + layeredLayout, + verticallyStackedLayout, } from '../../layout'; import { durationToWidth, @@ -30,9 +34,13 @@ import { REACT_WORK_BORDER_SIZE, } from '../constants'; -export class FlamechartView extends View { - flamechart: Flamechart; - profilerData: ReactProfilerData; +class FlamechartStackLayerView extends View { + /** Layer to display */ + stackLayer: FlamechartStackLayer; + + /** A set of `stackLayer`'s frames, for efficient lookup. */ + stackFrameSet: Set; + intrinsicSize: Size; hoveredStackFrame: FlamechartStackFrame | null = null; @@ -41,15 +49,15 @@ export class FlamechartView extends View { constructor( surface: Surface, frame: Rect, - flamechart: Flamechart, - profilerData: ReactProfilerData, + stackLayer: FlamechartStackLayer, + duration: number, ) { super(surface, frame); - this.flamechart = flamechart; - this.profilerData = profilerData; + this.stackLayer = stackLayer; + this.stackFrameSet = new Set(stackLayer); this.intrinsicSize = { - width: this.profilerData.duration, - height: this.flamechart.length * FLAMECHART_FRAME_HEIGHT, + width: duration, + height: FLAMECHART_FRAME_HEIGHT, }; } @@ -57,19 +65,30 @@ export class FlamechartView extends View { return this.intrinsicSize; } - setHoveredFlamechartNode(hoveredStackFrame: FlamechartStackFrame | null) { + setHoveredFlamechartStackFrame( + hoveredStackFrame: FlamechartStackFrame | null, + ) { if (this.hoveredStackFrame === hoveredStackFrame) { - return; + return; // We're already hovering over this frame + } + + // Only care about frames displayed by this view. + const stackFrameToSet = + hoveredStackFrame && this.stackFrameSet.has(hoveredStackFrame) + ? hoveredStackFrame + : null; + if (this.hoveredStackFrame === stackFrameToSet) { + return; // Resulting state is unchanged } - this.hoveredStackFrame = hoveredStackFrame; + this.hoveredStackFrame = stackFrameToSet; this.setNeedsDisplay(); } draw(context: CanvasRenderingContext2D) { const { frame, - flamechart, - hoveredStackFrame: hoveredFlamechartNode, + stackLayer, + hoveredStackFrame, intrinsicSize, visibleArea, } = this; @@ -88,89 +107,73 @@ export class FlamechartView extends View { const scaleFactor = positioningScaleFactor(intrinsicSize.width, frame); - for (let i = 0; i < flamechart.length; i++) { - const stackLayer = flamechart[i]; + for (let i = 0; i < stackLayer.length; i++) { + const {name, timestamp, duration} = stackLayer[i]; - const layerY = Math.floor(frame.origin.y + i * FLAMECHART_FRAME_HEIGHT); - if ( - layerY + FLAMECHART_FRAME_HEIGHT < visibleArea.origin.y || - visibleArea.origin.y + visibleArea.size.height < layerY - ) { - continue; // Not in view + const width = durationToWidth(duration, scaleFactor); + if (width < 1) { + continue; // Too small to render at this zoom level } - for (let j = 0; j < stackLayer.length; j++) { - const {name, timestamp, duration} = stackLayer[j]; - - const width = durationToWidth(duration, scaleFactor); - if (width < 1) { - continue; // Too small to render at this zoom level - } + const x = Math.floor(timestampToPosition(timestamp, scaleFactor, frame)); + const nodeRect: Rect = { + origin: {x, y: frame.origin.y}, + size: { + width: Math.floor(width - REACT_WORK_BORDER_SIZE), + height: Math.floor(FLAMECHART_FRAME_HEIGHT - REACT_WORK_BORDER_SIZE), + }, + }; + if (!rectIntersectsRect(nodeRect, visibleArea)) { + continue; // Not in view + } - const x = Math.floor( - timestampToPosition(timestamp, scaleFactor, frame), + const showHoverHighlight = hoveredStackFrame === stackLayer[i]; + context.fillStyle = showHoverHighlight + ? COLORS.FLAME_CHART_HOVER + : COLORS.FLAME_CHART; + + const drawableRect = rectIntersectionWithRect(nodeRect, visibleArea); + context.fillRect( + drawableRect.origin.x, + drawableRect.origin.y, + drawableRect.size.width, + drawableRect.size.height, + ); + + if (width > FLAMECHART_TEXT_PADDING * 2) { + const trimmedName = trimFlamechartText( + context, + name, + width - FLAMECHART_TEXT_PADDING * 2 + (x < 0 ? x : 0), ); - const nodeRect: Rect = { - origin: {x, y: layerY}, - size: { - width: Math.floor(width - REACT_WORK_BORDER_SIZE), - height: Math.floor( - FLAMECHART_FRAME_HEIGHT - REACT_WORK_BORDER_SIZE, - ), - }, - }; - if (!rectIntersectsRect(nodeRect, visibleArea)) { - continue; // Not in view - } - const showHoverHighlight = hoveredFlamechartNode === stackLayer[j]; - context.fillStyle = showHoverHighlight - ? COLORS.FLAME_CHART_HOVER - : COLORS.FLAME_CHART; - - const drawableRect = rectIntersectionWithRect(nodeRect, visibleArea); - context.fillRect( - drawableRect.origin.x, - drawableRect.origin.y, - drawableRect.size.width, - drawableRect.size.height, - ); + if (trimmedName !== null) { + context.fillStyle = COLORS.PRIORITY_LABEL; - if (width > FLAMECHART_TEXT_PADDING * 2) { - const trimmedName = trimFlamechartText( - context, - name, - width - FLAMECHART_TEXT_PADDING * 2 + (x < 0 ? x : 0), + // Prevent text from being drawn outside `viewableArea` + const textOverflowsViewableArea = !rectEqualToRect( + drawableRect, + nodeRect, ); - - if (trimmedName !== null) { - context.fillStyle = COLORS.PRIORITY_LABEL; - - // Prevent text from being drawn outside `viewableArea` - const textOverflowsViewableArea = !rectEqualToRect( - drawableRect, - nodeRect, - ); - if (textOverflowsViewableArea) { - context.save(); - context.rect( - drawableRect.origin.x, - drawableRect.origin.y, - drawableRect.size.width, - drawableRect.size.height, - ); - context.clip(); - } - - context.fillText( - trimmedName, - x + FLAMECHART_TEXT_PADDING - (x < 0 ? x : 0), - layerY + FLAMECHART_FRAME_HEIGHT / 2, + if (textOverflowsViewableArea) { + context.save(); + context.rect( + drawableRect.origin.x, + drawableRect.origin.y, + drawableRect.size.width, + drawableRect.size.height, ); + context.clip(); + } - if (textOverflowsViewableArea) { - context.restore(); - } + context.fillText( + trimmedName, + nodeRect.origin.x + FLAMECHART_TEXT_PADDING - (x < 0 ? x : 0), + nodeRect.origin.y + FLAMECHART_FRAME_HEIGHT / 2, + ); + + if (textOverflowsViewableArea) { + context.restore(); } } } @@ -181,39 +184,19 @@ export class FlamechartView extends View { * @private */ handleHover(interaction: HoverInteraction) { - const {flamechart, frame, intrinsicSize, onHover, visibleArea} = this; - if (!onHover) { - return; - } - + const {stackLayer, frame, intrinsicSize, onHover, visibleArea} = this; const {location} = interaction.payload; - if (!rectContainsPoint(location, visibleArea)) { - onHover(null); + if (!onHover || !rectContainsPoint(location, visibleArea)) { return; } - // Identify the layer being hovered over - const adjustedCanvasMouseY = location.y - frame.origin.y; - const layerIndex = Math.floor( - adjustedCanvasMouseY / FLAMECHART_FRAME_HEIGHT, - ); - if (layerIndex < 0 || layerIndex >= flamechart.length) { - onHover(null); - return; - } - const layer = flamechart[layerIndex]; - - if (!layer) { - return null; - } - // Find the node being hovered over. const scaleFactor = positioningScaleFactor(intrinsicSize.width, frame); let startIndex = 0; - let stopIndex = layer.length - 1; + let stopIndex = stackLayer.length - 1; while (startIndex <= stopIndex) { const currentIndex = Math.floor((startIndex + stopIndex) / 2); - const flamechartStackFrame = layer[currentIndex]; + const flamechartStackFrame = stackLayer[currentIndex]; const {timestamp, duration} = flamechartStackFrame; const width = durationToWidth(duration, scaleFactor); @@ -241,3 +224,124 @@ export class FlamechartView extends View { } } } + +export class FlamechartView extends View { + flamechart: Flamechart; + duration: number; + + intrinsicSize: Size; + + flamechartRowViews: FlamechartStackLayerView[] = []; + /** Container view that vertically stacks flamechart rows */ + verticalStackView: StaticLayoutView; + /** View that layers a background color view behind `verticalStackView` */ + layerStackView: StaticLayoutView; + + onHover: ((node: FlamechartStackFrame | null) => void) | null = null; + + constructor( + surface: Surface, + frame: Rect, + flamechart: Flamechart, + duration: number, + ) { + super(surface, frame); + this.flamechart = flamechart; + this.duration = duration; + this.intrinsicSize = { + width: duration, + height: this.flamechart.length * FLAMECHART_FRAME_HEIGHT, + }; + + this.verticalStackView = new StaticLayoutView( + surface, + frame, + verticallyStackedLayout, + [], + ); + + // Use a plain background view to prevent gaps from appearing between + // flamechartRowViews. + const colorView = new ColorView(surface, frame, COLORS.BACKGROUND); + this.layerStackView = new StaticLayoutView(surface, frame, layeredLayout, [ + colorView, + this.verticalStackView, + ]); + this.layerStackView.superview = this; + } + + desiredSize() { + // TODO: Replace this with one calculated by verticalStackView + return this.intrinsicSize; + } + + setHoveredFlamechartStackFrame( + hoveredStackFrame: FlamechartStackFrame | null, + ) { + this.flamechartRowViews.forEach(rowView => + rowView.setHoveredFlamechartStackFrame(hoveredStackFrame), + ); + } + + setOnHover(onHover: (node: FlamechartStackFrame | null) => void) { + this.onHover = onHover; + this.flamechartRowViews.forEach(rowView => (rowView.onHover = onHover)); + } + + setNeedsDisplay() { + super.setNeedsDisplay(); + this.layerStackView.setNeedsDisplay(); + } + + layoutSubviews() { + if (this.flamechartRowViews.length !== this.flamechart.length) { + // TODO: Remove existing row views from verticalStackView + this.flamechartRowViews = this.flamechart.map(stackLayer => { + const rowView = new FlamechartStackLayerView( + this.surface, + this.frame, + stackLayer, + this.duration, + ); + this.verticalStackView.addSubview(rowView); + rowView.onHover = this.onHover; + return rowView; + }); + this.setNeedsDisplay(); + } + + // Lay out subviews + const {layerStackView} = this; + layerStackView.setFrame(this.frame); + layerStackView.setVisibleArea(this.visibleArea); + } + + draw(context: CanvasRenderingContext2D) { + this.layerStackView.displayIfNeeded(context); + } + + /** + * @private + */ + handleHover(interaction: HoverInteraction) { + const {onHover, visibleArea} = this; + if (!onHover) { + return; + } + + const {location} = interaction.payload; + if (!rectContainsPoint(location, visibleArea)) { + // Clear out any hovered flamechart stack frame + onHover(null); + } + } + + handleInteractionAndPropagateToSubviews(interaction: Interaction) { + switch (interaction.type) { + case 'hover': + this.handleHover(interaction); + break; + } + this.layerStackView.handleInteractionAndPropagateToSubviews(interaction); + } +} diff --git a/src/layout/ColorView.js b/src/layout/ColorView.js new file mode 100644 index 0000000000000..6c86df0b78524 --- /dev/null +++ b/src/layout/ColorView.js @@ -0,0 +1,29 @@ +// @flow + +import type {Rect} from './geometry'; + +import {Surface} from './Surface'; +import {View} from './View'; + +/** + * View that fills its visible area with a CSS color. + */ +export class ColorView extends View { + _color: string; + + constructor(surface: Surface, frame: Rect, color: string) { + super(surface, frame); + this._color = color; + } + + draw(context: CanvasRenderingContext2D) { + const {_color, visibleArea} = this; + context.fillStyle = _color; + context.fillRect( + visibleArea.origin.x, + visibleArea.origin.y, + visibleArea.size.width, + visibleArea.size.height, + ); + } +} diff --git a/src/layout/StaticLayoutView.js b/src/layout/StaticLayoutView.js index 3d00912f51127..0dc19d6a0592d 100644 --- a/src/layout/StaticLayoutView.js +++ b/src/layout/StaticLayoutView.js @@ -18,13 +18,17 @@ export const layeredLayout: Layouter = (views, frame) => subview.setFrame(frame); }); +/** + * Stacks `views` vertically in `frame`. All views in `views` will have their + * widths set to the frame's width. + */ export const verticallyStackedLayout: Layouter = (views, frame) => { let currentY = frame.origin.y; views.forEach(view => { const desiredSize = view.desiredSize(); const height = desiredSize ? desiredSize.height - : frame.size.height - currentY; + : frame.origin.y + frame.size.height - currentY; const proposedFrame = { origin: {x: frame.origin.x, y: currentY}, size: {width: frame.size.width, height}, diff --git a/src/layout/VerticalScrollView.js b/src/layout/VerticalScrollView.js index 906e7f377a2eb..4a85139191679 100644 --- a/src/layout/VerticalScrollView.js +++ b/src/layout/VerticalScrollView.js @@ -37,7 +37,6 @@ function clamp(min: number, max: number, value: number): number { export class VerticalScrollView extends View { contentView: View; - intrinsicContentHeight: number; scrollState: VerticalScrollState = { offsetY: 0, @@ -52,14 +51,12 @@ export class VerticalScrollView extends View { surface: Surface, frame: Rect, contentView: View, - intrinsicContentHeight: number, stateDeriver?: (state: VerticalScrollState) => VerticalScrollState, onStateChange?: (state: VerticalScrollState) => void, ) { super(surface, frame); this.contentView = contentView; contentView.superview = this; - this.intrinsicContentHeight = intrinsicContentHeight; if (stateDeriver) this.stateDeriver = stateDeriver; if (onStateChange) this.onStateChange = onStateChange; } @@ -78,6 +75,13 @@ export class VerticalScrollView extends View { layoutSubviews() { const {offsetY} = this.scrollState; + const desiredSize = this.contentView.desiredSize(); + + const remainingHeight = this.frame.size.height; + const desiredHeight = desiredSize ? desiredSize.height : 0; + // Force last view to take up at least all remaining vertical space. + const height = Math.max(desiredHeight, remainingHeight); + const proposedFrame = { origin: { x: this.frame.origin.x, @@ -85,7 +89,7 @@ export class VerticalScrollView extends View { }, size: { width: this.frame.size.width, - height: this.intrinsicContentHeight, + height, }, }; this.contentView.setFrame(proposedFrame); diff --git a/src/layout/index.js b/src/layout/index.js index df9f5d6e9b675..0ed792c85a27c 100644 --- a/src/layout/index.js +++ b/src/layout/index.js @@ -1,6 +1,7 @@ // @flow export * from './geometry'; +export * from './ColorView'; export * from './HorizontalPanAndZoomView'; export * from './StaticLayoutView'; export * from './Surface'; From 2c79e71ff975a45f925ca7bf83f2e857853ec976 Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Thu, 30 Jul 2020 21:46:59 +0800 Subject: [PATCH 060/116] Add Chromium flamechart colors (#96) --- src/canvas/__tests__/colors-test.js | 86 ++++++++++++++++++++++ src/canvas/colors.js | 106 ++++++++++++++++++++++++++++ src/canvas/constants.js | 3 +- src/canvas/views/FlamechartView.js | 34 ++++++++- 4 files changed, 224 insertions(+), 5 deletions(-) create mode 100644 src/canvas/__tests__/colors-test.js create mode 100644 src/canvas/colors.js diff --git a/src/canvas/__tests__/colors-test.js b/src/canvas/__tests__/colors-test.js new file mode 100644 index 0000000000000..2b04bffc415a4 --- /dev/null +++ b/src/canvas/__tests__/colors-test.js @@ -0,0 +1,86 @@ +'use strict'; + +import {hslaColorToString, dimmedColor, ColorGenerator} from '../colors'; + +describe(hslaColorToString, () => { + it('should transform colors to strings', () => { + expect(hslaColorToString({h: 1, s: 2, l: 3, a: 4})).toEqual( + 'hsl(1deg 2% 3% / 4)', + ); + expect(hslaColorToString({h: 3.14, s: 6.28, l: 1.68, a: 100})).toEqual( + 'hsl(3.14deg 6.28% 1.68% / 100)', + ); + }); +}); + +describe(dimmedColor, () => { + it('should dim luminosity using delta', () => { + expect(dimmedColor({h: 1, s: 2, l: 3, a: 4}, 3)).toEqual({ + h: 1, + s: 2, + l: 0, + a: 4, + }); + expect(dimmedColor({h: 1, s: 2, l: 3, a: 4}, -3)).toEqual({ + h: 1, + s: 2, + l: 6, + a: 4, + }); + }); +}); + +describe(ColorGenerator, () => { + describe(ColorGenerator.prototype.colorForID, () => { + it('should generate a color for an ID', () => { + expect(new ColorGenerator().colorForID('123')).toMatchInlineSnapshot(` + Object { + "a": 1, + "h": 190, + "l": 80, + "s": 67, + } + `); + }); + + it('should generate colors deterministically given an ID', () => { + expect(new ColorGenerator().colorForID('id1')).toEqual( + new ColorGenerator().colorForID('id1'), + ); + expect(new ColorGenerator().colorForID('id2')).toEqual( + new ColorGenerator().colorForID('id2'), + ); + }); + + it('should generate different colors for different IDs', () => { + expect(new ColorGenerator().colorForID('id1')).not.toEqual( + new ColorGenerator().colorForID('id2'), + ); + }); + + it('should return colors that have been set manually', () => { + const generator = new ColorGenerator(); + const manualColor = {h: 1, s: 2, l: 3, a: 4}; + generator.setColorForID('id with set color', manualColor); + expect(generator.colorForID('id with set color')).toEqual(manualColor); + expect(generator.colorForID('some other id')).not.toEqual(manualColor); + }); + + it('should generate colors from fixed color spaces', () => { + const generator = new ColorGenerator(1, 2, 3, 4); + expect(generator.colorForID('123')).toEqual({h: 1, s: 2, l: 3, a: 4}); + expect(generator.colorForID('234')).toEqual({h: 1, s: 2, l: 3, a: 4}); + }); + + it('should generate colors from range color spaces', () => { + const generator = new ColorGenerator( + {min: 0, max: 360, count: 2}, + 2, + 3, + 4, + ); + expect(generator.colorForID('123')).toEqual({h: 0, s: 2, l: 3, a: 4}); + expect(generator.colorForID('234')).toEqual({h: 360, s: 2, l: 3, a: 4}); + }); + }); +}); diff --git a/src/canvas/colors.js b/src/canvas/colors.js new file mode 100644 index 0000000000000..70d53c425b6fa --- /dev/null +++ b/src/canvas/colors.js @@ -0,0 +1,106 @@ +// @flow + +type ColorSpace = number | {|min: number, max: number, count?: number|}; + +// Docstrings from https://www.w3schools.com/css/css_colors_hsl.asp +type HslaColor = $ReadOnly<{| + /** Hue is a degree on the color wheel from 0 to 360. 0 is red, 120 is green, and 240 is blue. */ + h: number, + /** Saturation is a percentage value, 0% means a shade of gray, and 100% is the full color. */ + s: number, + /** Lightness is a percentage, 0% is black, 50% is neither light or dark, 100% is white. */ + l: number, + /** Alpha is a percentage, 0% is fully transparent, and 100 is not transparent at all. */ + a: number, +|}>; + +export function hslaColorToString({h, s, l, a}: HslaColor): string { + return `hsl(${h}deg ${s}% ${l}% / ${a})`; +} + +export function dimmedColor(color: HslaColor, dimDelta: number): HslaColor { + return { + ...color, + l: color.l - dimDelta, + }; +} + +// Source: https://source.chromium.org/chromium/chromium/src/+/master:out/Debug/gen/devtools/platform/utilities.js;l=120 +function hashCode(string: string): number { + // Hash algorithm for substrings is described in "Über die Komplexität der Multiplikation in + // eingeschränkten Branchingprogrammmodellen" by Woelfe. + // http://opendatastructures.org/versions/edition-0.1d/ods-java/node33.html#SECTION00832000000000000000 + const p = (1 << 30) * 4 - 5; // prime: 2^32 - 5 + const z = 0x5033d967; // 32 bits from random.org + const z2 = 0x59d2f15d; // random odd 32 bit number + let s = 0; + let zi = 1; + for (let i = 0; i < string.length; i++) { + const xi = string.charCodeAt(i) * z2; + s = (s + zi * xi) % p; + zi = (zi * z) % p; + } + s = (s + zi * (p - 1)) % p; + return Math.abs(s | 0); +} + +function indexToValueInSpace(index: number, space: ColorSpace): number { + if (typeof space === 'number') { + return space; + } + const count = space.count || space.max - space.min; + index %= count; + return ( + space.min + Math.floor((index / (count - 1)) * (space.max - space.min)) + ); +} + +/** + * Deterministic color generator. + * + * Adapted from: https://source.chromium.org/chromium/chromium/src/+/master:out/Debug/gen/devtools/common/Color.js + */ +export class ColorGenerator { + _hueSpace: ColorSpace; + _satSpace: ColorSpace; + _lightnessSpace: ColorSpace; + _alphaSpace: ColorSpace; + _colors: Map; + + constructor( + hueSpace?: ColorSpace, + satSpace?: ColorSpace, + lightnessSpace?: ColorSpace, + alphaSpace?: ColorSpace, + ) { + this._hueSpace = hueSpace || {min: 0, max: 360}; + this._satSpace = satSpace || 67; + this._lightnessSpace = lightnessSpace || 80; + this._alphaSpace = alphaSpace || 1; + this._colors = new Map(); + } + + setColorForID(id: string, color: HslaColor) { + this._colors.set(id, color); + } + + colorForID(id: string): HslaColor { + const cachedColor = this._colors.get(id); + if (cachedColor) { + return cachedColor; + } + const color = this._generateColorForID(id); + this._colors.set(id, color); + return color; + } + + _generateColorForID(id: string): HslaColor { + const hash = hashCode(id); + return { + h: indexToValueInSpace(hash, this._hueSpace), + s: indexToValueInSpace(hash >> 8, this._satSpace), + l: indexToValueInSpace(hash >> 16, this._lightnessSpace), + a: indexToValueInSpace(hash >> 24, this._alphaSpace), + }; + } +} diff --git a/src/canvas/constants.js b/src/canvas/constants.js index b510af7cc168b..4f7c19bd3efb6 100644 --- a/src/canvas/constants.js +++ b/src/canvas/constants.js @@ -12,6 +12,7 @@ export const BAR_HORIZONTAL_SPACING = 1; export const BAR_SPACER_SIZE = 6; export const MIN_BAR_WIDTH = 1; export const SECTION_GUTTER_SIZE = 4; +export const COLOR_HOVER_DIM_DELTA = 5; export const INTERVAL_TIMES = [ 1, @@ -61,8 +62,6 @@ export const EVENT_ROW_HEIGHT_FIXED = export const COLORS = Object.freeze({ BACKGROUND: '#ffffff', - FLAME_CHART: '#fff79f', - FLAME_CHART_HOVER: '#ffe900', OTHER_SCRIPT: '#fff791', OTHER_SCRIPT_HOVER: '#ffea00', PRIORITY_BACKGROUND: '#ededf0', diff --git a/src/canvas/views/FlamechartView.js b/src/canvas/views/FlamechartView.js index a6e0c0a340275..22b3daa964e4f 100644 --- a/src/canvas/views/FlamechartView.js +++ b/src/canvas/views/FlamechartView.js @@ -31,8 +31,35 @@ import { FLAMECHART_FONT_SIZE, FLAMECHART_FRAME_HEIGHT, FLAMECHART_TEXT_PADDING, + COLOR_HOVER_DIM_DELTA, REACT_WORK_BORDER_SIZE, } from '../constants'; +import {ColorGenerator, dimmedColor, hslaColorToString} from '../colors'; + +// Source: https://source.chromium.org/chromium/chromium/src/+/master:out/Debug/gen/devtools/timeline/TimelineUIUtils.js;l=2109;drc=fb32e928d79707a693351b806b8710b2f6b7d399 +const colorGenerator = new ColorGenerator( + {min: 30, max: 330}, + {min: 50, max: 80, count: 3}, + 85, +); +colorGenerator.setColorForID('', {h: 43.6, s: 45.8, l: 90.6, a: 100}); + +function defaultHslaColorForStackFrame({scriptUrl}: FlamechartStackFrame) { + return colorGenerator.colorForID(scriptUrl || ''); +} + +function defaultColorForStackFrame(stackFrame: FlamechartStackFrame): string { + const color = defaultHslaColorForStackFrame(stackFrame); + return hslaColorToString(color); +} + +function hoverColorForStackFrame(stackFrame: FlamechartStackFrame): string { + const color = dimmedColor( + defaultHslaColorForStackFrame(stackFrame), + COLOR_HOVER_DIM_DELTA, + ); + return hslaColorToString(color); +} class FlamechartStackLayerView extends View { /** Layer to display */ @@ -108,7 +135,8 @@ class FlamechartStackLayerView extends View { const scaleFactor = positioningScaleFactor(intrinsicSize.width, frame); for (let i = 0; i < stackLayer.length; i++) { - const {name, timestamp, duration} = stackLayer[i]; + const stackFrame = stackLayer[i]; + const {name, timestamp, duration} = stackFrame; const width = durationToWidth(duration, scaleFactor); if (width < 1) { @@ -129,8 +157,8 @@ class FlamechartStackLayerView extends View { const showHoverHighlight = hoveredStackFrame === stackLayer[i]; context.fillStyle = showHoverHighlight - ? COLORS.FLAME_CHART_HOVER - : COLORS.FLAME_CHART; + ? hoverColorForStackFrame(stackFrame) + : defaultColorForStackFrame(stackFrame); const drawableRect = rectIntersectionWithRect(nodeRect, visibleArea); context.fillRect( From e0c29fbbc72bc93101e4660feeaaa29bcc5e09cd Mon Sep 17 00:00:00 2001 From: Vikash Chander Date: Fri, 31 Jul 2020 16:28:57 +0530 Subject: [PATCH 061/116] Text animation fix (#106) * fix: text link transition * fix: add font-size --- src/ImportPage.css | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ImportPage.css b/src/ImportPage.css index dce625045e0cf..a6425cf7dee94 100644 --- a/src/ImportPage.css +++ b/src/ImportPage.css @@ -15,10 +15,12 @@ .link { color: #282c34; transition: 0.2s; + font-size: calc(10px + 1.5vmin); } .link:hover { color: #61dafb; transition: 0.2s; + font-size: calc(10px + 1.5vmin); } kbd { From 4385a12558228a1b2a4bb7d18a00b7f90a93d53e Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Mon, 3 Aug 2020 08:12:05 +0800 Subject: [PATCH 062/116] [Improve base View][1/n] Add subview handling to View (#99) Summary This PR begins a stack of PRs that improves the base `View` class implemented in #80. This PR adds subview management to `View`, as there was a lot of duplicated subview handling code present in almost all our `View` subclasses. This also brings us closer to UIKit's `UIView`, which also handles its own subviews. Implements #95. Test Plan * `yarn start`: nothing broken * `yarn lint` * `yarn flow`: no errors in affected code * `yarn test` --- src/canvas/views/FlamechartView.js | 16 +--- src/canvas/views/ReactEventsView.js | 2 +- src/canvas/views/ReactMeasuresView.js | 2 +- src/layout/HorizontalPanAndZoomView.js | 18 ++--- src/layout/StaticLayoutView.js | 31 +------ src/layout/Surface.js | 4 + src/layout/VerticalScrollView.js | 18 ++--- src/layout/View.js | 108 ++++++++++++++++++++++--- 8 files changed, 118 insertions(+), 81 deletions(-) diff --git a/src/canvas/views/FlamechartView.js b/src/canvas/views/FlamechartView.js index 22b3daa964e4f..3f8bfaf2e2054 100644 --- a/src/canvas/views/FlamechartView.js +++ b/src/canvas/views/FlamechartView.js @@ -244,7 +244,7 @@ class FlamechartStackLayerView extends View { onHover(null); } - handleInteractionAndPropagateToSubviews(interaction: Interaction) { + handleInteraction(interaction: Interaction) { switch (interaction.type) { case 'hover': this.handleHover(interaction); @@ -295,7 +295,7 @@ export class FlamechartView extends View { colorView, this.verticalStackView, ]); - this.layerStackView.superview = this; + this.addSubview(this.layerStackView); } desiredSize() { @@ -316,11 +316,6 @@ export class FlamechartView extends View { this.flamechartRowViews.forEach(rowView => (rowView.onHover = onHover)); } - setNeedsDisplay() { - super.setNeedsDisplay(); - this.layerStackView.setNeedsDisplay(); - } - layoutSubviews() { if (this.flamechartRowViews.length !== this.flamechart.length) { // TODO: Remove existing row views from verticalStackView @@ -344,10 +339,6 @@ export class FlamechartView extends View { layerStackView.setVisibleArea(this.visibleArea); } - draw(context: CanvasRenderingContext2D) { - this.layerStackView.displayIfNeeded(context); - } - /** * @private */ @@ -364,12 +355,11 @@ export class FlamechartView extends View { } } - handleInteractionAndPropagateToSubviews(interaction: Interaction) { + handleInteraction(interaction: Interaction) { switch (interaction.type) { case 'hover': this.handleHover(interaction); break; } - this.layerStackView.handleInteractionAndPropagateToSubviews(interaction); } } diff --git a/src/canvas/views/ReactEventsView.js b/src/canvas/views/ReactEventsView.js index 9eff893965cd7..c18bdcf614542 100644 --- a/src/canvas/views/ReactEventsView.js +++ b/src/canvas/views/ReactEventsView.js @@ -236,7 +236,7 @@ export class ReactEventsView extends View { onHover(null); } - handleInteractionAndPropagateToSubviews(interaction: Interaction) { + handleInteraction(interaction: Interaction) { switch (interaction.type) { case 'hover': this.handleHover(interaction); diff --git a/src/canvas/views/ReactMeasuresView.js b/src/canvas/views/ReactMeasuresView.js index a77d9c4c9ee10..3c5b68a1f1eb1 100644 --- a/src/canvas/views/ReactMeasuresView.js +++ b/src/canvas/views/ReactMeasuresView.js @@ -294,7 +294,7 @@ export class ReactMeasuresView extends View { onHover(null); } - handleInteractionAndPropagateToSubviews(interaction: Interaction) { + handleInteraction(interaction: Interaction) { switch (interaction.type) { case 'hover': this.handleHover(interaction); diff --git a/src/layout/HorizontalPanAndZoomView.js b/src/layout/HorizontalPanAndZoomView.js index 23dd46348e4ef..9ef416088518e 100644 --- a/src/layout/HorizontalPanAndZoomView.js +++ b/src/layout/HorizontalPanAndZoomView.js @@ -53,6 +53,10 @@ function zoomLevelAndIntrinsicWidthToFrameWidth( } export class HorizontalPanAndZoomView extends View { + /** + * Reference to the content view. This view is also the only view in + * `this.subviews`. + */ contentView: View; intrinsicContentWidth: number; @@ -79,17 +83,12 @@ export class HorizontalPanAndZoomView extends View { ) { super(surface, frame); this.contentView = contentView; - contentView.superview = this; + this.addSubview(this.contentView); this.intrinsicContentWidth = intrinsicContentWidth; if (stateDeriver) this.stateDeriver = stateDeriver; if (onStateChange) this.onStateChange = onStateChange; } - setNeedsDisplay() { - super.setNeedsDisplay(); - this.contentView.setNeedsDisplay(); - } - setFrame(newFrame: Rect) { super.setFrame(newFrame); @@ -116,10 +115,6 @@ export class HorizontalPanAndZoomView extends View { this.contentView.setVisibleArea(this.visibleArea); } - draw(context: CanvasRenderingContext2D) { - this.contentView.displayIfNeeded(context); - } - isPanning = false; handleHorizontalPanStart(interaction: HorizontalPanStartInteraction) { @@ -214,7 +209,7 @@ export class HorizontalPanAndZoomView extends View { this.updateState(offsetAdjustedState); } - handleInteractionAndPropagateToSubviews(interaction: Interaction) { + handleInteraction(interaction: Interaction) { switch (interaction.type) { case 'horizontal-pan-start': this.handleHorizontalPanStart(interaction); @@ -234,7 +229,6 @@ export class HorizontalPanAndZoomView extends View { this.handleWheelZoom(interaction); break; } - this.contentView.handleInteractionAndPropagateToSubviews(interaction); } /** diff --git a/src/layout/StaticLayoutView.js b/src/layout/StaticLayoutView.js index 0dc19d6a0592d..e54dfb268d00a 100644 --- a/src/layout/StaticLayoutView.js +++ b/src/layout/StaticLayoutView.js @@ -1,6 +1,5 @@ // @flow -import type {Interaction} from '../useCanvasInteraction'; import type {Rect} from './geometry'; import {Surface} from './Surface'; @@ -39,28 +38,17 @@ export const verticallyStackedLayout: Layouter = (views, frame) => { }; export class StaticLayoutView extends View { - subviews: View[] = []; layouter: Layouter; constructor( surface: Surface, frame: Rect, layouter: Layouter, - subviews: View[], + initialSubviews: View[], ) { super(surface, frame); this.layouter = layouter; - subviews.forEach(subview => this.addSubview(subview)); - } - - setNeedsDisplay() { - super.setNeedsDisplay(); - this.subviews.forEach(subview => subview.setNeedsDisplay()); - } - - addSubview(view: View) { - this.subviews.push(view); - view.superview = this; + initialSubviews.forEach(subview => this.addSubview(subview)); } layoutSubviews() { @@ -76,19 +64,4 @@ export class StaticLayoutView extends View { } }); } - - draw(context: CanvasRenderingContext2D) { - const {subviews, visibleArea} = this; - subviews.forEach(subview => { - if (rectIntersectsRect(visibleArea, subview.visibleArea)) { - subview.displayIfNeeded(context); - } - }); - } - - handleInteractionAndPropagateToSubviews(interaction: Interaction) { - this.subviews.forEach(subview => - subview.handleInteractionAndPropagateToSubviews(interaction), - ); - } } diff --git a/src/layout/Surface.js b/src/layout/Surface.js index 0df492da83922..39b7e1e1f8baf 100644 --- a/src/layout/Surface.js +++ b/src/layout/Surface.js @@ -8,6 +8,10 @@ import {getCanvasContext} from '../canvas/canvasUtils'; import {View} from './View'; import {zeroPoint} from './geometry'; +/** + * Represents the canvas surface and a view heirarchy. A surface is also the + * place where all interactions enter the view heirarchy. + */ export class Surface { rootView: ?View; context: ?CanvasRenderingContext2D; diff --git a/src/layout/VerticalScrollView.js b/src/layout/VerticalScrollView.js index 4a85139191679..2122c8151f5d6 100644 --- a/src/layout/VerticalScrollView.js +++ b/src/layout/VerticalScrollView.js @@ -36,6 +36,10 @@ function clamp(min: number, max: number, value: number): number { } export class VerticalScrollView extends View { + /** + * Reference to the content view. This view is also the only view in + * `this.subviews`. + */ contentView: View; scrollState: VerticalScrollState = { @@ -56,16 +60,11 @@ export class VerticalScrollView extends View { ) { super(surface, frame); this.contentView = contentView; - contentView.superview = this; + this.addSubview(this.contentView); if (stateDeriver) this.stateDeriver = stateDeriver; if (onStateChange) this.onStateChange = onStateChange; } - setNeedsDisplay() { - super.setNeedsDisplay(); - this.contentView.setNeedsDisplay(); - } - setFrame(newFrame: Rect) { super.setFrame(newFrame); @@ -96,10 +95,6 @@ export class VerticalScrollView extends View { this.contentView.setVisibleArea(this.visibleArea); } - draw(context: CanvasRenderingContext2D) { - this.contentView.displayIfNeeded(context); - } - isPanning = false; handleVerticalPanStart(interaction: VerticalPanStartInteraction) { @@ -151,7 +146,7 @@ export class VerticalScrollView extends View { }); } - handleInteractionAndPropagateToSubviews(interaction: Interaction) { + handleInteraction(interaction: Interaction) { switch (interaction.type) { case 'vertical-pan-start': this.handleVerticalPanStart(interaction); @@ -166,7 +161,6 @@ export class VerticalScrollView extends View { this.handleWheelPlain(interaction); break; } - this.contentView.handleInteractionAndPropagateToSubviews(interaction); } /** diff --git a/src/layout/View.js b/src/layout/View.js index d34c80aec3566..4f606cde8d503 100644 --- a/src/layout/View.js +++ b/src/layout/View.js @@ -12,6 +12,10 @@ import { zeroRect, } from './geometry'; +/** + * Base view class that can be subclassed to draw custom content or manage + * subclasses. + */ export class View { surface: Surface; @@ -19,10 +23,26 @@ export class View { visibleArea: Rect; superview: ?View; + subviews: View[] = []; - /** Whether this view needs to be drawn. */ + /** + * Whether this view needs to be drawn. + * + * NOTE: Do not set directly! Use `setNeedsDisplay`. + * + * @see setNeedsDisplay + * @private + */ needsDisplay = true; - /** Whether the heirarchy below this view has subviews that need display. */ + + /** + * Whether the heirarchy below this view has subviews that need display. + * + * NOTE: Do not set directly! Use `setSubviewsNeedDisplay`. + * + * @see setSubviewsNeedDisplay + * @private + */ subviewsNeedDisplay = false; constructor(surface: Surface, frame: Rect, visibleArea: Rect = frame) { @@ -36,15 +56,13 @@ export class View { * * Downward propagating; once called, all subviews of this view should also * be invalidated. - * - * Subclasses with subviews should override this method and call - * `setNeedsDisplay` on its subviews. */ setNeedsDisplay() { this.needsDisplay = true; if (this.superview) { this.superview.setSubviewsNeedDisplay(); } + this.subviews.forEach(subview => subview.setNeedsDisplay()); } /** @@ -52,6 +70,8 @@ export class View { * * Upward propagating; once called, all superviews of this view should also * have `subviewsNeedDisplay` = true. + * + * @private */ setSubviewsNeedDisplay() { this.subviewsNeedDisplay = true; @@ -86,14 +106,19 @@ export class View { desiredSize(): ?Size {} /** - * Layout self and subviews. - * - * Call `setNeedsDisplay` if we are to redraw. - * - * To be overwritten by subclasses. + * Appends `view` to the list of this view's `subviews`. */ - layoutSubviews() {} + addSubview(view: View) { + this.subviews.push(view); + view.superview = this; + } + /** + * Executes the display flow if this view needs to be drawn. + * + * 1. Lays out subviews with `layoutSubviews`. + * 2. Draws content with `draw`. + */ displayIfNeeded(context: CanvasRenderingContext2D) { if ( (this.needsDisplay || this.subviewsNeedDisplay) && @@ -107,7 +132,64 @@ export class View { } } - draw(context: CanvasRenderingContext2D) {} + /** + * Layout self and subviews. + * + * Implementations should call `setNeedsDisplay` if a draw is required. + * + * To be overwritten by subclasses that wish to manage their subviews' + * layout. + * + * NOTE: Do not call directly! Use `displayIfNeeded`. + * + * @see displayIfNeeded + */ + layoutSubviews() {} + + /** + * Draw the contents of this view in the given canvas `context`. + * + * Defaults to drawing this view's `subviews`. + * + * To be overwritten by subclasses that wish to draw custom content. + * + * NOTE: Do not call directly! Use `displayIfNeeded`. + * + * @see displayIfNeeded + */ + draw(context: CanvasRenderingContext2D) { + const {subviews, visibleArea} = this; + subviews.forEach(subview => { + if (rectIntersectsRect(visibleArea, subview.visibleArea)) { + subview.displayIfNeeded(context); + } + }); + } + + /** + * Handle an `interaction`. + * + * To be overwritten by subclasses that wish to handle interactions. + */ + // Internal note: Do not call directly! Use + // `handleInteractionAndPropagateToSubviews` so that interactions are + // propagated to subviews. + handleInteraction(interaction: Interaction) {} - handleInteractionAndPropagateToSubviews(interaction: Interaction): ?boolean {} + /** + * Handle an `interaction` and propagates it to all of this view's + * `subviews`. + * + * NOTE: Should not be overridden! Subclasses should override + * `handleInteraction` instead. + * + * @see handleInteraction + * @protected + */ + handleInteractionAndPropagateToSubviews(interaction: Interaction) { + this.handleInteraction(interaction); + this.subviews.forEach(subview => + subview.handleInteractionAndPropagateToSubviews(interaction), + ); + } } From 32a33b08cea55e7d55c187cb7b9923475bb7ab57 Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Mon, 3 Aug 2020 08:13:58 +0800 Subject: [PATCH 063/116] [Improve base View][2/n] Rationalize view layout system (#100) Summary The layout system was previously a bit of a mess. Only content views implemented the `desiredSize` method, and thus composing other views in `StaticLayoutView` was problematic as our layouters need `desiredSize` as a size hint. This (large) PR attempts to fix this by making some major changes to the layout system: 1. Increase the usefulness of layouters, by defining many more layouters and allowing them to be composed. They are currently not used, but were tested to work before I realized I didn't need them in this PR. 2. Move layouters to the base `View` class, allowing all views to have some default layout behavior. The default layout behavior is still a noop. 3. Add a default `desiredSize` implementation to `View`. The default implementation simply lays out its subviews, then hugs them. 4. Update `VerticalScrollView` and `HorizontalPanAndZoomView` to work with the new `View`. As these classes are essentially a combination of a layouter + an interactor, we may be able to split them into injectable functions in the future. 5. Update `FlamechartView` to work with the new `View`. As this view is basically composed from a bunch of layouty views and content views (think a React component that uses a bunch of other React components), it can now take advantage of layouters on the base `View`. Test Plan * `yarn lint` * `yarn flow`: no change in errors * `yarn start`: appears to be equally performant --- src/CanvasPage.js | 18 +- src/canvas/views/FlamechartView.js | 97 +++++------ src/layout/HorizontalPanAndZoomView.js | 8 +- src/layout/StaticLayoutView.js | 67 -------- src/layout/VerticalScrollView.js | 14 +- src/layout/View.js | 83 +++++++++- src/layout/geometry.js | 82 +++++++--- src/layout/index.js | 4 +- src/layout/layouter.js | 218 +++++++++++++++++++++++++ 9 files changed, 420 insertions(+), 171 deletions(-) delete mode 100644 src/layout/StaticLayoutView.js create mode 100644 src/layout/layouter.js diff --git a/src/CanvasPage.js b/src/CanvasPage.js index 3d021aedd6ffb..a2d960a6a35aa 100644 --- a/src/CanvasPage.js +++ b/src/CanvasPage.js @@ -16,7 +16,7 @@ import { HorizontalPanAndZoomView, VerticalScrollView, Surface, - StaticLayoutView, + View, layeredLayout, zeroPoint, verticallyStackedLayout, @@ -149,17 +149,15 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) { flamechartView, ); - const stackedZoomables = new StaticLayoutView( + const stackedZoomables = new View( surfaceRef.current, {origin: zeroPoint, size: {width, height}}, verticallyStackedLayout, - [ - axisMarkersView, - reactEventsView, - reactMeasuresView, - flamechartVScrollWrapper, - ], ); + stackedZoomables.addSubview(axisMarkersView); + stackedZoomables.addSubview(reactEventsView); + stackedZoomables.addSubview(reactMeasuresView); + stackedZoomables.addSubview(flamechartVScrollWrapper); const contentZoomWrapper = new HorizontalPanAndZoomView( surfaceRef.current, @@ -168,12 +166,12 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) { reactEventsView.intrinsicSize.width, ); - rootViewRef.current = new StaticLayoutView( + rootViewRef.current = new View( surfaceRef.current, {origin: zeroPoint, size: {width, height}}, layeredLayout, - [contentZoomWrapper], ); + rootViewRef.current.addSubview(contentZoomWrapper); surfaceRef.current.rootView = rootViewRef.current; }, [data, setHoveredEvent]); diff --git a/src/canvas/views/FlamechartView.js b/src/canvas/views/FlamechartView.js index 3f8bfaf2e2054..911e875fd6db6 100644 --- a/src/canvas/views/FlamechartView.js +++ b/src/canvas/views/FlamechartView.js @@ -10,14 +10,13 @@ import type {Rect, Size} from '../../layout'; import { ColorView, - View, Surface, - StaticLayoutView, + View, + layeredLayout, rectContainsPoint, rectEqualToRect, - rectIntersectsRect, rectIntersectionWithRect, - layeredLayout, + rectIntersectsRect, verticallyStackedLayout, } from '../../layout'; import { @@ -254,17 +253,12 @@ class FlamechartStackLayerView extends View { } export class FlamechartView extends View { - flamechart: Flamechart; - duration: number; - - intrinsicSize: Size; - flamechartRowViews: FlamechartStackLayerView[] = []; + /** Container view that vertically stacks flamechart rows */ - verticalStackView: StaticLayoutView; - /** View that layers a background color view behind `verticalStackView` */ - layerStackView: StaticLayoutView; + verticalStackView: View; + hoveredStackFrame: FlamechartStackFrame | null = null; onHover: ((node: FlamechartStackFrame | null) => void) | null = null; constructor( @@ -273,39 +267,46 @@ export class FlamechartView extends View { flamechart: Flamechart, duration: number, ) { - super(surface, frame); - this.flamechart = flamechart; - this.duration = duration; - this.intrinsicSize = { - width: duration, - height: this.flamechart.length * FLAMECHART_FRAME_HEIGHT, - }; + super(surface, frame, layeredLayout); + this.setDataAndUpdateSubviews(flamechart, duration); + } - this.verticalStackView = new StaticLayoutView( - surface, - frame, - verticallyStackedLayout, - [], - ); + setDataAndUpdateSubviews(flamechart: Flamechart, duration: number) { + const {surface, frame, onHover, hoveredStackFrame} = this; + + // Clear existing rows on data update + if (this.verticalStackView) { + this.removeAllSubviews(); + this.flamechartRowViews = []; + } - // Use a plain background view to prevent gaps from appearing between + this.verticalStackView = new View(surface, frame, verticallyStackedLayout); + this.flamechartRowViews = flamechart.map(stackLayer => { + const rowView = new FlamechartStackLayerView( + surface, + frame, + stackLayer, + duration, + ); + this.verticalStackView.addSubview(rowView); + + // Update states + rowView.onHover = onHover; + rowView.setHoveredFlamechartStackFrame(hoveredStackFrame); + return rowView; + }); + + // Add a plain background view to prevent gaps from appearing between // flamechartRowViews. const colorView = new ColorView(surface, frame, COLORS.BACKGROUND); - this.layerStackView = new StaticLayoutView(surface, frame, layeredLayout, [ - colorView, - this.verticalStackView, - ]); - this.addSubview(this.layerStackView); - } - - desiredSize() { - // TODO: Replace this with one calculated by verticalStackView - return this.intrinsicSize; + this.addSubview(colorView); + this.addSubview(this.verticalStackView); } setHoveredFlamechartStackFrame( hoveredStackFrame: FlamechartStackFrame | null, ) { + this.hoveredStackFrame = hoveredStackFrame; this.flamechartRowViews.forEach(rowView => rowView.setHoveredFlamechartStackFrame(hoveredStackFrame), ); @@ -316,27 +317,9 @@ export class FlamechartView extends View { this.flamechartRowViews.forEach(rowView => (rowView.onHover = onHover)); } - layoutSubviews() { - if (this.flamechartRowViews.length !== this.flamechart.length) { - // TODO: Remove existing row views from verticalStackView - this.flamechartRowViews = this.flamechart.map(stackLayer => { - const rowView = new FlamechartStackLayerView( - this.surface, - this.frame, - stackLayer, - this.duration, - ); - this.verticalStackView.addSubview(rowView); - rowView.onHover = this.onHover; - return rowView; - }); - this.setNeedsDisplay(); - } - - // Lay out subviews - const {layerStackView} = this; - layerStackView.setFrame(this.frame); - layerStackView.setVisibleArea(this.visibleArea); + desiredSize() { + // Ignore the wishes of the background color view + return this.verticalStackView.desiredSize(); } /** diff --git a/src/layout/HorizontalPanAndZoomView.js b/src/layout/HorizontalPanAndZoomView.js index 9ef416088518e..288f54939fedb 100644 --- a/src/layout/HorizontalPanAndZoomView.js +++ b/src/layout/HorizontalPanAndZoomView.js @@ -96,6 +96,12 @@ export class HorizontalPanAndZoomView extends View { this.updateState(this.panAndZoomState); } + desiredSize() { + // We don't want our superview to fit to our content; we'll fit whatever + // frame we're given. + return null; + } + layoutSubviews() { const {offsetX, zoomLevel} = this.panAndZoomState; const proposedFrame = { @@ -112,7 +118,7 @@ export class HorizontalPanAndZoomView extends View { }, }; this.contentView.setFrame(proposedFrame); - this.contentView.setVisibleArea(this.visibleArea); + super.layoutSubviews(); } isPanning = false; diff --git a/src/layout/StaticLayoutView.js b/src/layout/StaticLayoutView.js deleted file mode 100644 index e54dfb268d00a..0000000000000 --- a/src/layout/StaticLayoutView.js +++ /dev/null @@ -1,67 +0,0 @@ -// @flow - -import type {Rect} from './geometry'; - -import {Surface} from './Surface'; -import {View} from './View'; -import { - rectIntersectsRect, - rectIntersectionWithRect, - zeroRect, -} from './geometry'; - -export type Layouter = (views: View[], containingFrame: Rect) => void; - -export const layeredLayout: Layouter = (views, frame) => - views.forEach(subview => { - subview.setFrame(frame); - }); - -/** - * Stacks `views` vertically in `frame`. All views in `views` will have their - * widths set to the frame's width. - */ -export const verticallyStackedLayout: Layouter = (views, frame) => { - let currentY = frame.origin.y; - views.forEach(view => { - const desiredSize = view.desiredSize(); - const height = desiredSize - ? desiredSize.height - : frame.origin.y + frame.size.height - currentY; - const proposedFrame = { - origin: {x: frame.origin.x, y: currentY}, - size: {width: frame.size.width, height}, - }; - view.setFrame(proposedFrame); - currentY += height; - }); -}; - -export class StaticLayoutView extends View { - layouter: Layouter; - - constructor( - surface: Surface, - frame: Rect, - layouter: Layouter, - initialSubviews: View[], - ) { - super(surface, frame); - this.layouter = layouter; - initialSubviews.forEach(subview => this.addSubview(subview)); - } - - layoutSubviews() { - const {frame, layouter, subviews, visibleArea} = this; - layouter(subviews, frame); - subviews.forEach(subview => { - if (rectIntersectsRect(visibleArea, subview.frame)) { - subview.setVisibleArea( - rectIntersectionWithRect(visibleArea, subview.frame), - ); - } else { - subview.setVisibleArea(zeroRect); - } - }); - } -} diff --git a/src/layout/VerticalScrollView.js b/src/layout/VerticalScrollView.js index 2122c8151f5d6..fdc82a8117a81 100644 --- a/src/layout/VerticalScrollView.js +++ b/src/layout/VerticalScrollView.js @@ -72,14 +72,20 @@ export class VerticalScrollView extends View { this.updateState(this.scrollState); } + desiredSize() { + // We don't want our superview to fit to our content; we'll fit whatever + // frame we're given. + return null; + } + layoutSubviews() { const {offsetY} = this.scrollState; const desiredSize = this.contentView.desiredSize(); - const remainingHeight = this.frame.size.height; + const minimumHeight = this.frame.size.height; const desiredHeight = desiredSize ? desiredSize.height : 0; - // Force last view to take up at least all remaining vertical space. - const height = Math.max(desiredHeight, remainingHeight); + // Force view to take up at least all remaining vertical space. + const height = Math.max(desiredHeight, minimumHeight); const proposedFrame = { origin: { @@ -92,7 +98,7 @@ export class VerticalScrollView extends View { }, }; this.contentView.setFrame(proposedFrame); - this.contentView.setVisibleArea(this.visibleArea); + super.layoutSubviews(); } isPanning = false; diff --git a/src/layout/View.js b/src/layout/View.js index 4f606cde8d503..7b51bd55ddab9 100644 --- a/src/layout/View.js +++ b/src/layout/View.js @@ -2,15 +2,19 @@ import type {Interaction} from '../useCanvasInteraction'; import type {Rect, Size} from './geometry'; +import type {Layouter} from './layouter'; import {Surface} from './Surface'; import { - rectIntersectsRect, rectEqualToRect, + rectIntersectionWithRect, + rectIntersectsRect, sizeIsEmpty, sizeIsValid, + unionOfRects, zeroRect, } from './geometry'; +import {noopLayout, viewsToLayout, collapseLayoutIntoViews} from './layouter'; /** * Base view class that can be subclassed to draw custom content or manage @@ -25,6 +29,9 @@ export class View { superview: ?View; subviews: View[] = []; + /** An injected function that lays out our subviews. */ + layouter: Layouter; + /** * Whether this view needs to be drawn. * @@ -45,9 +52,15 @@ export class View { */ subviewsNeedDisplay = false; - constructor(surface: Surface, frame: Rect, visibleArea: Rect = frame) { + constructor( + surface: Surface, + frame: Rect, + layouter: Layouter = noopLayout, + visibleArea: Rect = frame, + ) { this.surface = surface; this.frame = frame; + this.layouter = layouter; this.visibleArea = visibleArea; } @@ -103,16 +116,57 @@ export class View { } } - desiredSize(): ?Size {} + /** + * A size that can be used as a hint by layout functions. + * + * Implementations should typically return the intrinsic content size or a + * size that fits all the view's content. + * + * The default implementation returns a size that fits all the view's + * subviews. + * + * Can be overridden by subclasses. + */ + desiredSize(): ?Size { + if (this.needsDisplay) { + this.layoutSubviews(); + } + const frames = this.subviews.map(subview => subview.frame); + return unionOfRects(...frames).size; + } /** * Appends `view` to the list of this view's `subviews`. */ addSubview(view: View) { + if (this.subviews.includes(view)) { + return; + } this.subviews.push(view); view.superview = this; } + /** + * Breaks the subview-superview relationship between `view` and this view, if + * `view` is a subview of this view. + */ + removeSubview(view: View) { + const subviewIndex = this.subviews.indexOf(view); + if (subviewIndex === -1) { + return; + } + view.superview = undefined; + this.subviews.splice(subviewIndex, 1); + } + + /** + * Removes all subviews from this view. + */ + removeAllSubviews() { + this.subviews.forEach(subview => (subview.superview = undefined)); + this.subviews = []; + } + /** * Executes the display flow if this view needs to be drawn. * @@ -137,14 +191,31 @@ export class View { * * Implementations should call `setNeedsDisplay` if a draw is required. * - * To be overwritten by subclasses that wish to manage their subviews' - * layout. + * The default implementation uses `this.layouter` to lay out subviews. + * + * Can be overwritten by subclasses that wish to manually manage their + * subviews' layout. * * NOTE: Do not call directly! Use `displayIfNeeded`. * * @see displayIfNeeded */ - layoutSubviews() {} + layoutSubviews() { + const {frame, layouter, subviews, visibleArea} = this; + const existingLayout = viewsToLayout(subviews); + const newLayout = layouter(existingLayout, frame); + collapseLayoutIntoViews(newLayout); + + subviews.forEach((subview, subviewIndex) => { + if (rectIntersectsRect(visibleArea, subview.frame)) { + subview.setVisibleArea( + rectIntersectionWithRect(visibleArea, subview.frame), + ); + } else { + subview.setVisibleArea(zeroRect); + } + }); + } /** * Draw the contents of this view in the given canvas `context`. diff --git a/src/layout/geometry.js b/src/layout/geometry.js index 57622279d217c..73425751eb608 100644 --- a/src/layout/geometry.js +++ b/src/layout/geometry.js @@ -7,6 +7,12 @@ export type Point = $ReadOnly; export type Size = $ReadOnly; export type Rect = $ReadOnly<{origin: Point, size: Size}>; +/** + * Alternative representation of `Rect`. + * A tuple of (`top`, `right`, `bottom`, `left`) coordinates. + */ +type RectBoundaries = [number, number, number, number]; + export const zeroPoint: Point = Object.freeze({x: 0, y: 0}); export const zeroSize: Size = Object.freeze({width: 0, height: 0}); export const zeroRect: Rect = Object.freeze({ @@ -37,9 +43,7 @@ export function sizeIsEmpty({width, height}: Size): boolean { return width <= 0 || height <= 0; } -function rectToBoundaryCoordinates( - rect: Rect, -): [number, number, number, number] { +function rectToBoundaries(rect: Rect): RectBoundaries { const top = rect.origin.y; const right = rect.origin.x + rect.size.width; const bottom = rect.origin.y + rect.size.height; @@ -47,9 +51,23 @@ function rectToBoundaryCoordinates( return [top, right, bottom, left]; } +function boundariesToRect(boundaries: RectBoundaries): Rect { + const [top, right, bottom, left] = boundaries; + return { + origin: { + x: left, + y: top, + }, + size: { + width: right - left, + height: bottom - top, + }, + }; +} + export function rectIntersectsRect(rect1: Rect, rect2: Rect): boolean { - const [top1, right1, bottom1, left1] = rectToBoundaryCoordinates(rect1); - const [top2, right2, bottom2, left2] = rectToBoundaryCoordinates(rect2); + const [top1, right1, bottom1, left1] = rectToBoundaries(rect1); + const [top2, right2, bottom2, left2] = rectToBoundaries(rect2); return !( right1 < left2 || right2 < left1 || @@ -62,27 +80,43 @@ export function rectIntersectsRect(rect1: Rect, rect2: Rect): boolean { * Prerequisite: rect1 must intersect with rect2. */ export function rectIntersectionWithRect(rect1: Rect, rect2: Rect): Rect { - const [top1, right1, bottom1, left1] = rectToBoundaryCoordinates(rect1); - const [top2, right2, bottom2, left2] = rectToBoundaryCoordinates(rect2); - - const intersectleft = Math.max(left1, left2); - const intersectRight = Math.min(right1, right2); - const intersectTop = Math.max(top1, top2); - const intersectBottom = Math.min(bottom1, bottom2); - - return { - origin: { - x: intersectleft, - y: intersectTop, - }, - size: { - width: intersectRight - intersectleft, - height: intersectBottom - intersectTop, - }, - }; + const [top1, right1, bottom1, left1] = rectToBoundaries(rect1); + const [top2, right2, bottom2, left2] = rectToBoundaries(rect2); + return boundariesToRect([ + Math.max(top1, top2), + Math.min(right1, right2), + Math.min(bottom1, bottom2), + Math.max(left1, left2), + ]); } export function rectContainsPoint({x, y}: Point, rect: Rect): boolean { - const [top, right, bottom, left] = rectToBoundaryCoordinates(rect); + const [top, right, bottom, left] = rectToBoundaries(rect); return left <= x && x <= right && top <= y && y <= bottom; } + +/** + * The smallest rectangle that contains all provided rects. + * + * @returns `zeroRect` if `rects` is empty. + */ +export function unionOfRects(...rects: Rect[]): Rect { + if (rects.length === 0) { + return zeroRect; + } + + const [firstRect, ...remainingRects] = rects; + const boundaryUnion = remainingRects + .map(rectToBoundaries) + .reduce((unionBoundaries, nextBoundaries): RectBoundaries => { + const [unionTop, unionRight, unionBottom, unionLeft] = unionBoundaries; + const [nextTop, nextRight, nextBottom, nextLeft] = nextBoundaries; + return [ + Math.min(unionTop, nextTop), + Math.max(unionRight, nextRight), + Math.max(unionBottom, nextBottom), + Math.min(unionLeft, nextLeft), + ]; + }, rectToBoundaries(firstRect)); + return boundariesToRect(boundaryUnion); +} diff --git a/src/layout/index.js b/src/layout/index.js index 0ed792c85a27c..76a5cb51ca424 100644 --- a/src/layout/index.js +++ b/src/layout/index.js @@ -1,9 +1,9 @@ // @flow -export * from './geometry'; export * from './ColorView'; export * from './HorizontalPanAndZoomView'; -export * from './StaticLayoutView'; export * from './Surface'; export * from './VerticalScrollView'; export * from './View'; +export * from './geometry'; +export * from './layouter'; diff --git a/src/layout/layouter.js b/src/layout/layouter.js new file mode 100644 index 0000000000000..5d62e0e91146a --- /dev/null +++ b/src/layout/layouter.js @@ -0,0 +1,218 @@ +// @flow + +import type {Rect} from './geometry'; +import type {View} from './View'; + +export type LayoutInfo = {|view: View, frame: Rect|}; +export type Layout = LayoutInfo[]; + +/** + * A function that takes a list of subviews, currently laid out in + * `existingLayout`, and lays them out into `containingFrame`. + */ +export type Layouter = ( + existingLayout: Layout, + containingFrame: Rect, +) => Layout; + +function viewToLayoutInfo(view: View): LayoutInfo { + return {view, frame: view.frame}; +} + +export function viewsToLayout(views: View[]): Layout { + return views.map(viewToLayoutInfo); +} + +/** + * Applies `layout`'s `frame`s to its corresponding `view`. + */ +export function collapseLayoutIntoViews(layout: Layout) { + layout.forEach(({view, frame}) => view.setFrame(frame)); +} + +/** + * A no-operation layout; does not modify the layout. + */ +export const noopLayout: Layouter = layout => layout; + +/** + * Layer views on top of each other. All views' frames will be set to + * `containerFrame`. + * + * Equivalent to composing: + * - `alignToContainerXLayout`, + * - `alignToContainerYLayout`, + * - `containerWidthLayout`, and + * - `containerHeightLayout`. + */ +export const layeredLayout: Layouter = (layout, containerFrame) => + layout.map(layoutInfo => ({...layoutInfo, frame: containerFrame})); + +/** + * Stacks `views` vertically in `frame`. All views in `views` will have their + * widths set to the frame's width. + */ +export const verticallyStackedLayout: Layouter = (layout, containerFrame) => { + let currentY = containerFrame.origin.y; + return layout.map(layoutInfo => { + const desiredSize = layoutInfo.view.desiredSize(); + const height = desiredSize + ? desiredSize.height + : containerFrame.origin.y + containerFrame.size.height - currentY; + const proposedFrame = { + origin: {x: containerFrame.origin.x, y: currentY}, + size: {width: containerFrame.size.width, height}, + }; + currentY += height; + return { + ...layoutInfo, + frame: proposedFrame, + }; + }); +}; + +/** + * A layouter that aligns all frames' lefts to the container frame's left. + */ +export const alignToContainerXLayout: Layouter = (layout, containerFrame) => { + return layout.map(layoutInfo => ({ + ...layoutInfo, + frame: { + origin: { + x: containerFrame.origin.x, + y: layoutInfo.frame.origin.y, + }, + size: layoutInfo.frame.size, + }, + })); +}; + +/** + * A layouter that aligns all frames' tops to the container frame's top. + */ +export const alignToContainerYLayout: Layouter = (layout, containerFrame) => { + return layout.map(layoutInfo => ({ + ...layoutInfo, + frame: { + origin: { + x: layoutInfo.frame.origin.x, + y: containerFrame.origin.y, + }, + size: layoutInfo.frame.size, + }, + })); +}; + +/** + * A layouter that sets all frames' widths to `containerFrame.size.width`. + */ +export const containerWidthLayout: Layouter = (layout, containerFrame) => { + return layout.map(layoutInfo => ({ + ...layoutInfo, + frame: { + origin: layoutInfo.frame.origin, + size: { + width: containerFrame.size.width, + height: layoutInfo.frame.size.height, + }, + }, + })); +}; + +/** + * A layouter that sets all frames' heights to `containerFrame.size.height`. + */ +export const containerHeightLayout: Layouter = (layout, containerFrame) => { + return layout.map(layoutInfo => ({ + ...layoutInfo, + frame: { + origin: layoutInfo.frame.origin, + size: { + width: layoutInfo.frame.size.width, + height: containerFrame.size.height, + }, + }, + })); +}; + +/** + * A layouter that sets all frames' heights to the desired height of its view. + * If the view has no desired size, the frame's height is set to 0. + */ +export const desiredHeightLayout: Layouter = layout => { + return layout.map(layoutInfo => { + const desiredSize = layoutInfo.view.desiredSize(); + const height = desiredSize ? desiredSize.height : 0; + return { + ...layoutInfo, + frame: { + origin: layoutInfo.frame.origin, + size: { + width: layoutInfo.frame.size.width, + height, + }, + }, + }; + }); +}; + +/** + * A layouter that sets all frames' heights to the height of the tallest frame. + */ +export const uniformMaxSubviewHeightLayout: Layouter = layout => { + const maxHeight = Math.max( + ...layout.map(layoutInfo => layoutInfo.frame.size.height), + ); + return layout.map(layoutInfo => ({ + ...layoutInfo, + frame: { + origin: layoutInfo.frame.origin, + size: { + width: layoutInfo.frame.size.width, + height: maxHeight, + }, + }, + })); +}; + +/** + * A layouter that sets heights in this fashion: + * - If a frame's height >= `containerFrame.size.height`, the frame is left unchanged. + * - Otherwise, sets the frame's height to `containerFrame.size.height`. + */ +export const atLeastContainerHeightLayout: Layouter = ( + layout, + containerFrame, +) => { + return layout.map(layoutInfo => ({ + ...layoutInfo, + frame: { + origin: layoutInfo.frame.origin, + size: { + width: layoutInfo.frame.size.width, + height: Math.max( + containerFrame.size.height, + layoutInfo.frame.size.height, + ), + }, + }, + })); +}; + +/** + * Create a layouter that applies each layouter in `layouters` in sequence. + */ +export function createComposedLayout(...layouters: Layouter[]): Layouter { + if (layouters.length === 0) { + return noopLayout; + } + + const composedLayout: Layouter = (layout, containerFrame) => { + return layouters.reduce( + (intermediateLayout, layouter) => + layouter(intermediateLayout, containerFrame), + layout, + ); + }; + return composedLayout; +} From ec3383b66f6fe1ebbe8a2268f5115cd42709aa4f Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Mon, 3 Aug 2020 08:15:57 +0800 Subject: [PATCH 064/116] [Improve base View][3/n] Add _ to views' private vars and methods (#101) --- src/CanvasPage.js | 2 +- src/canvas/views/FlamechartView.js | 104 ++++++++++---------- src/canvas/views/ReactEventsView.js | 50 +++++----- src/canvas/views/ReactMeasuresView.js | 81 ++++++++-------- src/canvas/views/TimeAxisMarkersView.js | 22 ++--- src/layout/HorizontalPanAndZoomView.js | 122 ++++++++++++------------ src/layout/Surface.js | 18 ++-- src/layout/VerticalScrollView.js | 91 +++++++++--------- src/layout/View.js | 35 +++---- 9 files changed, 270 insertions(+), 255 deletions(-) diff --git a/src/CanvasPage.js b/src/CanvasPage.js index a2d960a6a35aa..485413cfe2e23 100644 --- a/src/CanvasPage.js +++ b/src/CanvasPage.js @@ -163,7 +163,7 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) { surfaceRef.current, {origin: zeroPoint, size: {width, height}}, stackedZoomables, - reactEventsView.intrinsicSize.width, + data.duration, ); rootViewRef.current = new View( diff --git a/src/canvas/views/FlamechartView.js b/src/canvas/views/FlamechartView.js index 911e875fd6db6..6c21e27c786b0 100644 --- a/src/canvas/views/FlamechartView.js +++ b/src/canvas/views/FlamechartView.js @@ -62,15 +62,15 @@ function hoverColorForStackFrame(stackFrame: FlamechartStackFrame): string { class FlamechartStackLayerView extends View { /** Layer to display */ - stackLayer: FlamechartStackLayer; + _stackLayer: FlamechartStackLayer; /** A set of `stackLayer`'s frames, for efficient lookup. */ - stackFrameSet: Set; + _stackFrameSet: Set; - intrinsicSize: Size; + _intrinsicSize: Size; - hoveredStackFrame: FlamechartStackFrame | null = null; - onHover: ((node: FlamechartStackFrame | null) => void) | null = null; + _hoveredStackFrame: FlamechartStackFrame | null = null; + _onHover: ((node: FlamechartStackFrame | null) => void) | null = null; constructor( surface: Surface, @@ -79,43 +79,43 @@ class FlamechartStackLayerView extends View { duration: number, ) { super(surface, frame); - this.stackLayer = stackLayer; - this.stackFrameSet = new Set(stackLayer); - this.intrinsicSize = { + this._stackLayer = stackLayer; + this._stackFrameSet = new Set(stackLayer); + this._intrinsicSize = { width: duration, height: FLAMECHART_FRAME_HEIGHT, }; } desiredSize() { - return this.intrinsicSize; + return this._intrinsicSize; } setHoveredFlamechartStackFrame( hoveredStackFrame: FlamechartStackFrame | null, ) { - if (this.hoveredStackFrame === hoveredStackFrame) { + if (this._hoveredStackFrame === hoveredStackFrame) { return; // We're already hovering over this frame } // Only care about frames displayed by this view. const stackFrameToSet = - hoveredStackFrame && this.stackFrameSet.has(hoveredStackFrame) + hoveredStackFrame && this._stackFrameSet.has(hoveredStackFrame) ? hoveredStackFrame : null; - if (this.hoveredStackFrame === stackFrameToSet) { + if (this._hoveredStackFrame === stackFrameToSet) { return; // Resulting state is unchanged } - this.hoveredStackFrame = stackFrameToSet; + this._hoveredStackFrame = stackFrameToSet; this.setNeedsDisplay(); } draw(context: CanvasRenderingContext2D) { const { frame, - stackLayer, - hoveredStackFrame, - intrinsicSize, + _stackLayer, + _hoveredStackFrame, + _intrinsicSize, visibleArea, } = this; @@ -131,10 +131,10 @@ class FlamechartStackLayerView extends View { context.textBaseline = 'middle'; context.font = `${FLAMECHART_FONT_SIZE}px sans-serif`; - const scaleFactor = positioningScaleFactor(intrinsicSize.width, frame); + const scaleFactor = positioningScaleFactor(_intrinsicSize.width, frame); - for (let i = 0; i < stackLayer.length; i++) { - const stackFrame = stackLayer[i]; + for (let i = 0; i < _stackLayer.length; i++) { + const stackFrame = _stackLayer[i]; const {name, timestamp, duration} = stackFrame; const width = durationToWidth(duration, scaleFactor); @@ -154,7 +154,7 @@ class FlamechartStackLayerView extends View { continue; // Not in view } - const showHoverHighlight = hoveredStackFrame === stackLayer[i]; + const showHoverHighlight = _hoveredStackFrame === _stackLayer[i]; context.fillStyle = showHoverHighlight ? hoverColorForStackFrame(stackFrame) : defaultColorForStackFrame(stackFrame); @@ -210,26 +210,26 @@ class FlamechartStackLayerView extends View { /** * @private */ - handleHover(interaction: HoverInteraction) { - const {stackLayer, frame, intrinsicSize, onHover, visibleArea} = this; + _handleHover(interaction: HoverInteraction) { + const {_stackLayer, frame, _intrinsicSize, _onHover, visibleArea} = this; const {location} = interaction.payload; - if (!onHover || !rectContainsPoint(location, visibleArea)) { + if (!_onHover || !rectContainsPoint(location, visibleArea)) { return; } // Find the node being hovered over. - const scaleFactor = positioningScaleFactor(intrinsicSize.width, frame); + const scaleFactor = positioningScaleFactor(_intrinsicSize.width, frame); let startIndex = 0; - let stopIndex = stackLayer.length - 1; + let stopIndex = _stackLayer.length - 1; while (startIndex <= stopIndex) { const currentIndex = Math.floor((startIndex + stopIndex) / 2); - const flamechartStackFrame = stackLayer[currentIndex]; + const flamechartStackFrame = _stackLayer[currentIndex]; const {timestamp, duration} = flamechartStackFrame; const width = durationToWidth(duration, scaleFactor); const x = Math.floor(timestampToPosition(timestamp, scaleFactor, frame)); if (x <= location.x && x + width >= location.x) { - onHover(flamechartStackFrame); + _onHover(flamechartStackFrame); return; } @@ -240,26 +240,26 @@ class FlamechartStackLayerView extends View { } } - onHover(null); + _onHover(null); } handleInteraction(interaction: Interaction) { switch (interaction.type) { case 'hover': - this.handleHover(interaction); + this._handleHover(interaction); break; } } } export class FlamechartView extends View { - flamechartRowViews: FlamechartStackLayerView[] = []; + _flamechartRowViews: FlamechartStackLayerView[] = []; /** Container view that vertically stacks flamechart rows */ - verticalStackView: View; + _verticalStackView: View; - hoveredStackFrame: FlamechartStackFrame | null = null; - onHover: ((node: FlamechartStackFrame | null) => void) | null = null; + _hoveredStackFrame: FlamechartStackFrame | null = null; + _onHover: ((node: FlamechartStackFrame | null) => void) | null = null; constructor( surface: Surface, @@ -272,27 +272,27 @@ export class FlamechartView extends View { } setDataAndUpdateSubviews(flamechart: Flamechart, duration: number) { - const {surface, frame, onHover, hoveredStackFrame} = this; + const {surface, frame, _onHover, _hoveredStackFrame} = this; // Clear existing rows on data update - if (this.verticalStackView) { + if (this._verticalStackView) { this.removeAllSubviews(); - this.flamechartRowViews = []; + this._flamechartRowViews = []; } - this.verticalStackView = new View(surface, frame, verticallyStackedLayout); - this.flamechartRowViews = flamechart.map(stackLayer => { + this._verticalStackView = new View(surface, frame, verticallyStackedLayout); + this._flamechartRowViews = flamechart.map(stackLayer => { const rowView = new FlamechartStackLayerView( surface, frame, stackLayer, duration, ); - this.verticalStackView.addSubview(rowView); + this._verticalStackView.addSubview(rowView); // Update states - rowView.onHover = onHover; - rowView.setHoveredFlamechartStackFrame(hoveredStackFrame); + rowView._onHover = _onHover; + rowView.setHoveredFlamechartStackFrame(_hoveredStackFrame); return rowView; }); @@ -300,48 +300,48 @@ export class FlamechartView extends View { // flamechartRowViews. const colorView = new ColorView(surface, frame, COLORS.BACKGROUND); this.addSubview(colorView); - this.addSubview(this.verticalStackView); + this.addSubview(this._verticalStackView); } setHoveredFlamechartStackFrame( hoveredStackFrame: FlamechartStackFrame | null, ) { - this.hoveredStackFrame = hoveredStackFrame; - this.flamechartRowViews.forEach(rowView => + this._hoveredStackFrame = hoveredStackFrame; + this._flamechartRowViews.forEach(rowView => rowView.setHoveredFlamechartStackFrame(hoveredStackFrame), ); } setOnHover(onHover: (node: FlamechartStackFrame | null) => void) { - this.onHover = onHover; - this.flamechartRowViews.forEach(rowView => (rowView.onHover = onHover)); + this._onHover = onHover; + this._flamechartRowViews.forEach(rowView => (rowView._onHover = onHover)); } desiredSize() { // Ignore the wishes of the background color view - return this.verticalStackView.desiredSize(); + return this._verticalStackView.desiredSize(); } /** * @private */ - handleHover(interaction: HoverInteraction) { - const {onHover, visibleArea} = this; - if (!onHover) { + _handleHover(interaction: HoverInteraction) { + const {_onHover, visibleArea} = this; + if (!_onHover) { return; } const {location} = interaction.payload; if (!rectContainsPoint(location, visibleArea)) { // Clear out any hovered flamechart stack frame - onHover(null); + _onHover(null); } } handleInteraction(interaction: Interaction) { switch (interaction.type) { case 'hover': - this.handleHover(interaction); + this._handleHover(interaction); break; } } diff --git a/src/canvas/views/ReactEventsView.js b/src/canvas/views/ReactEventsView.js index c18bdcf614542..4b3f1c55b99a3 100644 --- a/src/canvas/views/ReactEventsView.js +++ b/src/canvas/views/ReactEventsView.js @@ -26,38 +26,38 @@ import { } from '../constants'; export class ReactEventsView extends View { - profilerData: ReactProfilerData; - intrinsicSize: Size; + _profilerData: ReactProfilerData; + _intrinsicSize: Size; - hoveredEvent: ReactEvent | null = null; + _hoveredEvent: ReactEvent | null = null; onHover: ((event: ReactEvent | null) => void) | null = null; constructor(surface: Surface, frame: Rect, profilerData: ReactProfilerData) { super(surface, frame); - this.profilerData = profilerData; + this._profilerData = profilerData; - this.intrinsicSize = { - width: this.profilerData.duration, + this._intrinsicSize = { + width: this._profilerData.duration, height: EVENT_ROW_HEIGHT_FIXED, }; } desiredSize() { - return this.intrinsicSize; + return this._intrinsicSize; } setHoveredEvent(hoveredEvent: ReactEvent | null) { - if (this.hoveredEvent === hoveredEvent) { + if (this._hoveredEvent === hoveredEvent) { return; } - this.hoveredEvent = hoveredEvent; + this._hoveredEvent = hoveredEvent; this.setNeedsDisplay(); } /** * Draw a single `ReactEvent` as a circle in the canvas. */ - drawSingleReactEvent( + _drawSingleReactEvent( context: CanvasRenderingContext2D, rect: Rect, event: ReactEvent, @@ -122,8 +122,8 @@ export class ReactEventsView extends View { draw(context: CanvasRenderingContext2D) { const { frame, - profilerData: {events}, - hoveredEvent, + _profilerData: {events}, + _hoveredEvent, visibleArea, } = this; @@ -137,13 +137,16 @@ export class ReactEventsView extends View { // Draw events const baseY = frame.origin.y + REACT_EVENT_ROW_PADDING; - const scaleFactor = positioningScaleFactor(this.intrinsicSize.width, frame); + const scaleFactor = positioningScaleFactor( + this._intrinsicSize.width, + frame, + ); events.forEach(event => { - if (event === hoveredEvent) { + if (event === _hoveredEvent) { return; } - this.drawSingleReactEvent( + this._drawSingleReactEvent( context, visibleArea, event, @@ -155,11 +158,11 @@ export class ReactEventsView extends View { // Draw the hovered and/or selected items on top so they stand out. // This is helpful if there are multiple (overlapping) items close to each other. - if (hoveredEvent !== null) { - this.drawSingleReactEvent( + if (_hoveredEvent !== null) { + this._drawSingleReactEvent( context, visibleArea, - hoveredEvent, + _hoveredEvent, baseY, scaleFactor, true, @@ -196,7 +199,7 @@ export class ReactEventsView extends View { /** * @private */ - handleHover(interaction: HoverInteraction) { + _handleHover(interaction: HoverInteraction) { const {frame, onHover, visibleArea} = this; if (!onHover) { return; @@ -209,9 +212,12 @@ export class ReactEventsView extends View { } const { - profilerData: {events}, + _profilerData: {events}, } = this; - const scaleFactor = positioningScaleFactor(this.intrinsicSize.width, frame); + const scaleFactor = positioningScaleFactor( + this._intrinsicSize.width, + frame, + ); const hoverTimestamp = positionToTimestamp(location.x, scaleFactor, frame); const eventTimestampAllowance = widthToDuration( REACT_EVENT_SIZE / 2, @@ -239,7 +245,7 @@ export class ReactEventsView extends View { handleInteraction(interaction: Interaction) { switch (interaction.type) { case 'hover': - this.handleHover(interaction); + this._handleHover(interaction); break; } } diff --git a/src/canvas/views/ReactMeasuresView.js b/src/canvas/views/ReactMeasuresView.js index 3c5b68a1f1eb1..1419d3fb705b7 100644 --- a/src/canvas/views/ReactMeasuresView.js +++ b/src/canvas/views/ReactMeasuresView.js @@ -24,58 +24,58 @@ import {REACT_TOTAL_NUM_LANES} from '../../constants'; const REACT_LANE_HEIGHT = REACT_WORK_SIZE + REACT_WORK_BORDER_SIZE; export class ReactMeasuresView extends View { - profilerData: ReactProfilerData; - intrinsicSize: Size; + _profilerData: ReactProfilerData; + _intrinsicSize: Size; - lanesToRender: ReactLane[]; - laneToMeasures: Map; + _lanesToRender: ReactLane[]; + _laneToMeasures: Map; - hoveredMeasure: ReactMeasure | null = null; + _hoveredMeasure: ReactMeasure | null = null; onHover: ((measure: ReactMeasure | null) => void) | null = null; constructor(surface: Surface, frame: Rect, profilerData: ReactProfilerData) { super(surface, frame); - this.profilerData = profilerData; - this.performPreflightComputations(); + this._profilerData = profilerData; + this._performPreflightComputations(); } - performPreflightComputations() { - this.lanesToRender = []; - this.laneToMeasures = new Map(); + _performPreflightComputations() { + this._lanesToRender = []; + this._laneToMeasures = new Map(); for (let lane: ReactLane = 0; lane < REACT_TOTAL_NUM_LANES; lane++) { // Hide lanes without any measures - const measuresForLane = this.profilerData.measures.filter(measure => + const measuresForLane = this._profilerData.measures.filter(measure => measure.lanes.includes(lane), ); if (measuresForLane.length) { - this.lanesToRender.push(lane); - this.laneToMeasures.set(lane, measuresForLane); + this._lanesToRender.push(lane); + this._laneToMeasures.set(lane, measuresForLane); } } - this.intrinsicSize = { - width: this.profilerData.duration, - height: this.lanesToRender.length * REACT_LANE_HEIGHT, + this._intrinsicSize = { + width: this._profilerData.duration, + height: this._lanesToRender.length * REACT_LANE_HEIGHT, }; } desiredSize() { - return this.intrinsicSize; + return this._intrinsicSize; } setHoveredMeasure(hoveredMeasure: ReactMeasure | null) { - if (this.hoveredMeasure === hoveredMeasure) { + if (this._hoveredMeasure === hoveredMeasure) { return; } - this.hoveredMeasure = hoveredMeasure; + this._hoveredMeasure = hoveredMeasure; this.setNeedsDisplay(); } /** * Draw a single `ReactMeasure` as a bar in the canvas. */ - drawSingleReactMeasure( + _drawSingleReactMeasure( context: CanvasRenderingContext2D, rect: Rect, measure: ReactMeasure, @@ -158,9 +158,9 @@ export class ReactMeasuresView extends View { draw(context: CanvasRenderingContext2D) { const { frame, - hoveredMeasure, - lanesToRender, - laneToMeasures, + _hoveredMeasure, + _lanesToRender, + _laneToMeasures, visibleArea, } = this; @@ -172,12 +172,15 @@ export class ReactMeasuresView extends View { visibleArea.size.height, ); - const scaleFactor = positioningScaleFactor(this.intrinsicSize.width, frame); + const scaleFactor = positioningScaleFactor( + this._intrinsicSize.width, + frame, + ); - for (let i = 0; i < lanesToRender.length; i++) { - const lane = lanesToRender[i]; + for (let i = 0; i < _lanesToRender.length; i++) { + const lane = _lanesToRender[i]; const baseY = frame.origin.y + i * REACT_LANE_HEIGHT; - const measuresForLane = laneToMeasures.get(lane); + const measuresForLane = _laneToMeasures.get(lane); if (!measuresForLane) { throw new Error( @@ -188,11 +191,11 @@ export class ReactMeasuresView extends View { // Draw measures for (let j = 0; j < measuresForLane.length; j++) { const measure = measuresForLane[j]; - const showHoverHighlight = hoveredMeasure === measure; + const showHoverHighlight = _hoveredMeasure === measure; const showGroupHighlight = - !!hoveredMeasure && hoveredMeasure.batchUID === measure.batchUID; + !!_hoveredMeasure && _hoveredMeasure.batchUID === measure.batchUID; - this.drawSingleReactMeasure( + this._drawSingleReactMeasure( context, visibleArea, measure, @@ -236,12 +239,12 @@ export class ReactMeasuresView extends View { /** * @private */ - handleHover(interaction: HoverInteraction) { + _handleHover(interaction: HoverInteraction) { const { frame, - intrinsicSize, - lanesToRender, - laneToMeasures, + _intrinsicSize, + _lanesToRender, + _laneToMeasures, onHover, visibleArea, } = this; @@ -260,19 +263,19 @@ export class ReactMeasuresView extends View { const renderedLaneIndex = Math.floor( adjustedCanvasMouseY / REACT_LANE_HEIGHT, ); - if (renderedLaneIndex < 0 || renderedLaneIndex >= lanesToRender.length) { + if (renderedLaneIndex < 0 || renderedLaneIndex >= _lanesToRender.length) { onHover(null); return; } - const lane = lanesToRender[renderedLaneIndex]; + const lane = _lanesToRender[renderedLaneIndex]; // Find the measure in `lane` being hovered over. // // Because data ranges may overlap, we want to find the last intersecting item. // This will always be the one on "top" (the one the user is hovering over). - const scaleFactor = positioningScaleFactor(intrinsicSize.width, frame); + const scaleFactor = positioningScaleFactor(_intrinsicSize.width, frame); const hoverTimestamp = positionToTimestamp(location.x, scaleFactor, frame); - const measures = laneToMeasures.get(lane); + const measures = _laneToMeasures.get(lane); if (!measures) { onHover(null); return; @@ -297,7 +300,7 @@ export class ReactMeasuresView extends View { handleInteraction(interaction: Interaction) { switch (interaction.type) { case 'hover': - this.handleHover(interaction); + this._handleHover(interaction); break; } } diff --git a/src/canvas/views/TimeAxisMarkersView.js b/src/canvas/views/TimeAxisMarkersView.js index 6d97ab1abef2e..0dcfbb4e3883d 100644 --- a/src/canvas/views/TimeAxisMarkersView.js +++ b/src/canvas/views/TimeAxisMarkersView.js @@ -28,27 +28,27 @@ import { } from '../constants'; export class TimeAxisMarkersView extends View { - totalDuration: number; - intrinsicSize: Size; + _totalDuration: number; + _intrinsicSize: Size; constructor(surface: Surface, frame: Rect, totalDuration: number) { super(surface, frame); - this.totalDuration = totalDuration; - this.intrinsicSize = { - width: this.totalDuration, + this._totalDuration = totalDuration; + this._intrinsicSize = { + width: this._totalDuration, height: HEADER_HEIGHT_FIXED, }; } desiredSize() { - return this.intrinsicSize; + return this._intrinsicSize; } // Time mark intervals vary based on the current zoom range and the time it represents. // In Chrome, these seem to range from 70-140 pixels wide. // Time wise, they represent intervals of e.g. 1s, 500ms, 200ms, 100ms, 50ms, 20ms. // Based on zoom, we should determine which amount to actually show. - getTimeTickInterval(scaleFactor: number): number { + _getTimeTickInterval(scaleFactor: number): number { for (let i = 0; i < INTERVAL_TIMES.length; i++) { const currentInterval = INTERVAL_TIMES[i]; const intervalWidth = durationToWidth(currentInterval, scaleFactor); @@ -60,12 +60,12 @@ export class TimeAxisMarkersView extends View { } draw(context: CanvasRenderingContext2D) { - const {frame, intrinsicSize, visibleArea} = this; + const {frame, _intrinsicSize, visibleArea} = this; const clippedFrame = { origin: frame.origin, size: { width: frame.size.width, - height: intrinsicSize.height, + height: _intrinsicSize.height, }, }; const drawableRect = rectIntersectionWithRect(clippedFrame, visibleArea); @@ -80,10 +80,10 @@ export class TimeAxisMarkersView extends View { ); const scaleFactor = positioningScaleFactor( - intrinsicSize.width, + _intrinsicSize.width, clippedFrame, ); - const interval = this.getTimeTickInterval(scaleFactor); + const interval = this._getTimeTickInterval(scaleFactor); const firstIntervalTimestamp = Math.ceil( positionToTimestamp( diff --git a/src/layout/HorizontalPanAndZoomView.js b/src/layout/HorizontalPanAndZoomView.js index 288f54939fedb..404e7d92552bc 100644 --- a/src/layout/HorizontalPanAndZoomView.js +++ b/src/layout/HorizontalPanAndZoomView.js @@ -53,23 +53,20 @@ function zoomLevelAndIntrinsicWidthToFrameWidth( } export class HorizontalPanAndZoomView extends View { - /** - * Reference to the content view. This view is also the only view in - * `this.subviews`. - */ - contentView: View; - intrinsicContentWidth: number; + _intrinsicContentWidth: number; - panAndZoomState: HorizontalPanAndZoomState = { + _panAndZoomState: HorizontalPanAndZoomState = { offsetX: 0, zoomLevel: 0.25, }; - stateDeriver: ( + _isPanning = false; + + _stateDeriver: ( state: HorizontalPanAndZoomState, ) => HorizontalPanAndZoomState = state => state; - onStateChange: (state: HorizontalPanAndZoomState) => void = () => {}; + _onStateChange: (state: HorizontalPanAndZoomState) => void = () => {}; constructor( surface: Surface, @@ -82,18 +79,17 @@ export class HorizontalPanAndZoomView extends View { onStateChange?: (state: HorizontalPanAndZoomState) => void, ) { super(surface, frame); - this.contentView = contentView; - this.addSubview(this.contentView); - this.intrinsicContentWidth = intrinsicContentWidth; - if (stateDeriver) this.stateDeriver = stateDeriver; - if (onStateChange) this.onStateChange = onStateChange; + this.addSubview(contentView); + this._intrinsicContentWidth = intrinsicContentWidth; + if (stateDeriver) this._stateDeriver = stateDeriver; + if (onStateChange) this._onStateChange = onStateChange; } setFrame(newFrame: Rect) { super.setFrame(newFrame); // Revalidate panAndZoomState - this.updateState(this.panAndZoomState); + this._updateState(this._panAndZoomState); } desiredSize() { @@ -102,8 +98,16 @@ export class HorizontalPanAndZoomView extends View { return null; } + /** + * Reference to the content view. This view is also the only view in + * `this.subviews`. + */ + get _contentView() { + return this.subviews[0]; + } + layoutSubviews() { - const {offsetX, zoomLevel} = this.panAndZoomState; + const {offsetX, zoomLevel} = this._panAndZoomState; const proposedFrame = { origin: { x: this.frame.origin.x + offsetX, @@ -112,42 +116,40 @@ export class HorizontalPanAndZoomView extends View { size: { width: zoomLevelAndIntrinsicWidthToFrameWidth( zoomLevel, - this.intrinsicContentWidth, + this._intrinsicContentWidth, ), height: this.frame.size.height, }, }; - this.contentView.setFrame(proposedFrame); + this._contentView.setFrame(proposedFrame); super.layoutSubviews(); } - isPanning = false; - - handleHorizontalPanStart(interaction: HorizontalPanStartInteraction) { + _handleHorizontalPanStart(interaction: HorizontalPanStartInteraction) { if (rectContainsPoint(interaction.payload.location, this.frame)) { - this.isPanning = true; + this._isPanning = true; } } - handleHorizontalPanMove(interaction: HorizontalPanMoveInteraction) { - if (!this.isPanning) { + _handleHorizontalPanMove(interaction: HorizontalPanMoveInteraction) { + if (!this._isPanning) { return; } - const {offsetX} = this.panAndZoomState; + const {offsetX} = this._panAndZoomState; const {movementX} = interaction.payload.event; - this.updateState({ - ...this.panAndZoomState, + this._updateState({ + ...this._panAndZoomState, offsetX: offsetX + movementX, }); } - handleHorizontalPanEnd(interaction: HorizontalPanEndInteraction) { - if (this.isPanning) { - this.isPanning = false; + _handleHorizontalPanEnd(interaction: HorizontalPanEndInteraction) { + if (this._isPanning) { + this._isPanning = false; } } - handleWheelPlain(interaction: WheelPlainInteraction) { + _handleWheelPlain(interaction: WheelPlainInteraction) { const { location, event: {deltaX, deltaY}, @@ -166,13 +168,13 @@ export class HorizontalPanAndZoomView extends View { return; } - this.updateState({ - ...this.panAndZoomState, - offsetX: this.panAndZoomState.offsetX - deltaX, + this._updateState({ + ...this._panAndZoomState, + offsetX: this._panAndZoomState.offsetX - deltaX, }); } - handleWheelZoom( + _handleWheelZoom( interaction: | WheelWithShiftInteraction | WheelWithControlInteraction @@ -191,48 +193,48 @@ export class HorizontalPanAndZoomView extends View { return; } - const zoomClampedState = this.clampedProposedStateZoomLevel({ - ...this.panAndZoomState, - zoomLevel: this.panAndZoomState.zoomLevel * (1 + 0.005 * -deltaY), + const zoomClampedState = this._clampedProposedStateZoomLevel({ + ...this._panAndZoomState, + zoomLevel: this._panAndZoomState.zoomLevel * (1 + 0.005 * -deltaY), }); // Determine where the mouse is, and adjust the offset so that point stays // centered after zooming. const oldMouseXInFrame = location.x - zoomClampedState.offsetX; const fractionalMouseX = - oldMouseXInFrame / this.contentView.frame.size.width; + oldMouseXInFrame / this._contentView.frame.size.width; const newContentWidth = zoomLevelAndIntrinsicWidthToFrameWidth( zoomClampedState.zoomLevel, - this.intrinsicContentWidth, + this._intrinsicContentWidth, ); const newMouseXInFrame = fractionalMouseX * newContentWidth; - const offsetAdjustedState = this.clampedProposedStateOffsetX({ + const offsetAdjustedState = this._clampedProposedStateOffsetX({ ...zoomClampedState, offsetX: location.x - newMouseXInFrame, }); - this.updateState(offsetAdjustedState); + this._updateState(offsetAdjustedState); } handleInteraction(interaction: Interaction) { switch (interaction.type) { case 'horizontal-pan-start': - this.handleHorizontalPanStart(interaction); + this._handleHorizontalPanStart(interaction); break; case 'horizontal-pan-move': - this.handleHorizontalPanMove(interaction); + this._handleHorizontalPanMove(interaction); break; case 'horizontal-pan-end': - this.handleHorizontalPanEnd(interaction); + this._handleHorizontalPanEnd(interaction); break; case 'wheel-plain': - this.handleWheelPlain(interaction); + this._handleWheelPlain(interaction); break; case 'wheel-shift': case 'wheel-control': case 'wheel-meta': - this.handleWheelZoom(interaction); + this._handleWheelZoom(interaction); break; } } @@ -240,13 +242,13 @@ export class HorizontalPanAndZoomView extends View { /** * @private */ - updateState(proposedState: HorizontalPanAndZoomState) { - const clampedState = this.stateDeriver( - this.clampedProposedState(proposedState), + _updateState(proposedState: HorizontalPanAndZoomState) { + const clampedState = this._stateDeriver( + this._clampedProposedState(proposedState), ); - if (!panAndZoomStatesAreEqual(clampedState, this.panAndZoomState)) { - this.panAndZoomState = clampedState; - this.onStateChange(this.panAndZoomState); + if (!panAndZoomStatesAreEqual(clampedState, this._panAndZoomState)) { + this._panAndZoomState = clampedState; + this._onStateChange(this._panAndZoomState); this.setNeedsDisplay(); } } @@ -254,12 +256,12 @@ export class HorizontalPanAndZoomView extends View { /** * @private */ - clampedProposedStateZoomLevel( + _clampedProposedStateZoomLevel( proposedState: HorizontalPanAndZoomState, ): HorizontalPanAndZoomState { // Content-based min zoom level to ensure that contentView's width >= our width. const minContentBasedZoomLevel = - this.frame.size.width / this.intrinsicContentWidth; + this.frame.size.width / this._intrinsicContentWidth; const minZoomLevel = Math.max(MIN_ZOOM_LEVEL, minContentBasedZoomLevel); return { ...proposedState, @@ -270,12 +272,12 @@ export class HorizontalPanAndZoomView extends View { /** * @private */ - clampedProposedStateOffsetX( + _clampedProposedStateOffsetX( proposedState: HorizontalPanAndZoomState, ): HorizontalPanAndZoomState { const newContentWidth = zoomLevelAndIntrinsicWidthToFrameWidth( proposedState.zoomLevel, - this.intrinsicContentWidth, + this._intrinsicContentWidth, ); return { ...proposedState, @@ -290,10 +292,10 @@ export class HorizontalPanAndZoomView extends View { /** * @private */ - clampedProposedState( + _clampedProposedState( proposedState: HorizontalPanAndZoomState, ): HorizontalPanAndZoomState { - const zoomClampedState = this.clampedProposedStateZoomLevel(proposedState); - return this.clampedProposedStateOffsetX(zoomClampedState); + const zoomClampedState = this._clampedProposedStateZoomLevel(proposedState); + return this._clampedProposedStateOffsetX(zoomClampedState); } } diff --git a/src/layout/Surface.js b/src/layout/Surface.js index 39b7e1e1f8baf..52ed723e30442 100644 --- a/src/layout/Surface.js +++ b/src/layout/Surface.js @@ -14,16 +14,16 @@ import {zeroPoint} from './geometry'; */ export class Surface { rootView: ?View; - context: ?CanvasRenderingContext2D; - canvasSize: ?Size; + _context: ?CanvasRenderingContext2D; + _canvasSize: ?Size; setCanvas(canvas: HTMLCanvasElement, canvasSize: Size) { - this.context = getCanvasContext( + this._context = getCanvasContext( canvas, canvasSize.height, canvasSize.width, ); - this.canvasSize = canvasSize; + this._canvasSize = canvasSize; if (this.rootView) { this.rootView.setNeedsDisplay(); @@ -31,19 +31,19 @@ export class Surface { } displayIfNeeded() { - const {rootView, canvasSize, context} = this; - if (!rootView || !context || !canvasSize) { + const {rootView, _canvasSize, _context} = this; + if (!rootView || !_context || !_canvasSize) { return; } rootView.setFrame({ origin: zeroPoint, - size: canvasSize, + size: _canvasSize, }); rootView.setVisibleArea({ origin: zeroPoint, - size: canvasSize, + size: _canvasSize, }); - rootView.displayIfNeeded(context); + rootView.displayIfNeeded(_context); } handleInteraction(interaction: Interaction) { diff --git a/src/layout/VerticalScrollView.js b/src/layout/VerticalScrollView.js index fdc82a8117a81..71e80ed3cda04 100644 --- a/src/layout/VerticalScrollView.js +++ b/src/layout/VerticalScrollView.js @@ -36,20 +36,16 @@ function clamp(min: number, max: number, value: number): number { } export class VerticalScrollView extends View { - /** - * Reference to the content view. This view is also the only view in - * `this.subviews`. - */ - contentView: View; - - scrollState: VerticalScrollState = { + _scrollState: VerticalScrollState = { offsetY: 0, }; - stateDeriver: (state: VerticalScrollState) => VerticalScrollState = state => + _isPanning = false; + + _stateDeriver: (state: VerticalScrollState) => VerticalScrollState = state => state; - onStateChange: (state: VerticalScrollState) => void = () => {}; + _onStateChange: (state: VerticalScrollState) => void = () => {}; constructor( surface: Surface, @@ -59,17 +55,16 @@ export class VerticalScrollView extends View { onStateChange?: (state: VerticalScrollState) => void, ) { super(surface, frame); - this.contentView = contentView; - this.addSubview(this.contentView); - if (stateDeriver) this.stateDeriver = stateDeriver; - if (onStateChange) this.onStateChange = onStateChange; + this.addSubview(contentView); + if (stateDeriver) this._stateDeriver = stateDeriver; + if (onStateChange) this._onStateChange = onStateChange; } setFrame(newFrame: Rect) { super.setFrame(newFrame); // Revalidate scrollState - this.updateState(this.scrollState); + this._updateState(this._scrollState); } desiredSize() { @@ -78,9 +73,17 @@ export class VerticalScrollView extends View { return null; } + /** + * Reference to the content view. This view is also the only view in + * `this.subviews`. + */ + get _contentView() { + return this.subviews[0]; + } + layoutSubviews() { - const {offsetY} = this.scrollState; - const desiredSize = this.contentView.desiredSize(); + const {offsetY} = this._scrollState; + const desiredSize = this._contentView.desiredSize(); const minimumHeight = this.frame.size.height; const desiredHeight = desiredSize ? desiredSize.height : 0; @@ -97,37 +100,35 @@ export class VerticalScrollView extends View { height, }, }; - this.contentView.setFrame(proposedFrame); + this._contentView.setFrame(proposedFrame); super.layoutSubviews(); } - isPanning = false; - - handleVerticalPanStart(interaction: VerticalPanStartInteraction) { + _handleVerticalPanStart(interaction: VerticalPanStartInteraction) { if (rectContainsPoint(interaction.payload.location, this.frame)) { - this.isPanning = true; + this._isPanning = true; } } - handleVerticalPanMove(interaction: VerticalPanMoveInteraction) { - if (!this.isPanning) { + _handleVerticalPanMove(interaction: VerticalPanMoveInteraction) { + if (!this._isPanning) { return; } - const {offsetY} = this.scrollState; + const {offsetY} = this._scrollState; const {movementY} = interaction.payload.event; - this.updateState({ - ...this.scrollState, + this._updateState({ + ...this._scrollState, offsetY: offsetY + movementY, }); } - handleVerticalPanEnd(interaction: VerticalPanEndInteraction) { - if (this.isPanning) { - this.isPanning = false; + _handleVerticalPanEnd(interaction: VerticalPanEndInteraction) { + if (this._isPanning) { + this._isPanning = false; } } - handleWheelPlain(interaction: WheelPlainInteraction) { + _handleWheelPlain(interaction: WheelPlainInteraction) { const { location, event: {deltaX, deltaY}, @@ -146,25 +147,25 @@ export class VerticalScrollView extends View { return; } - this.updateState({ - ...this.scrollState, - offsetY: this.scrollState.offsetY - deltaY, + this._updateState({ + ...this._scrollState, + offsetY: this._scrollState.offsetY - deltaY, }); } handleInteraction(interaction: Interaction) { switch (interaction.type) { case 'vertical-pan-start': - this.handleVerticalPanStart(interaction); + this._handleVerticalPanStart(interaction); break; case 'vertical-pan-move': - this.handleVerticalPanMove(interaction); + this._handleVerticalPanMove(interaction); break; case 'vertical-pan-end': - this.handleVerticalPanEnd(interaction); + this._handleVerticalPanEnd(interaction); break; case 'wheel-plain': - this.handleWheelPlain(interaction); + this._handleWheelPlain(interaction); break; } } @@ -172,13 +173,13 @@ export class VerticalScrollView extends View { /** * @private */ - updateState(proposedState: VerticalScrollState) { - const clampedState = this.stateDeriver( - this.clampedProposedState(proposedState), + _updateState(proposedState: VerticalScrollState) { + const clampedState = this._stateDeriver( + this._clampedProposedState(proposedState), ); - if (!scrollStatesAreEqual(clampedState, this.scrollState)) { - this.scrollState = clampedState; - this.onStateChange(this.scrollState); + if (!scrollStatesAreEqual(clampedState, this._scrollState)) { + this._scrollState = clampedState; + this._onStateChange(this._scrollState); this.setNeedsDisplay(); } } @@ -186,12 +187,12 @@ export class VerticalScrollView extends View { /** * @private */ - clampedProposedState( + _clampedProposedState( proposedState: VerticalScrollState, ): VerticalScrollState { return { offsetY: clamp( - -(this.contentView.frame.size.height - this.frame.size.height), + -(this._contentView.frame.size.height - this.frame.size.height), 0, proposedState.offsetY, ), diff --git a/src/layout/View.js b/src/layout/View.js index 7b51bd55ddab9..a8b42c7b68dde 100644 --- a/src/layout/View.js +++ b/src/layout/View.js @@ -29,8 +29,11 @@ export class View { superview: ?View; subviews: View[] = []; - /** An injected function that lays out our subviews. */ - layouter: Layouter; + /** + * An injected function that lays out our subviews. + * @private + */ + _layouter: Layouter; /** * Whether this view needs to be drawn. @@ -40,7 +43,7 @@ export class View { * @see setNeedsDisplay * @private */ - needsDisplay = true; + _needsDisplay = true; /** * Whether the heirarchy below this view has subviews that need display. @@ -50,7 +53,7 @@ export class View { * @see setSubviewsNeedDisplay * @private */ - subviewsNeedDisplay = false; + _subviewsNeedDisplay = false; constructor( surface: Surface, @@ -60,7 +63,7 @@ export class View { ) { this.surface = surface; this.frame = frame; - this.layouter = layouter; + this._layouter = layouter; this.visibleArea = visibleArea; } @@ -71,9 +74,9 @@ export class View { * be invalidated. */ setNeedsDisplay() { - this.needsDisplay = true; + this._needsDisplay = true; if (this.superview) { - this.superview.setSubviewsNeedDisplay(); + this.superview._setSubviewsNeedDisplay(); } this.subviews.forEach(subview => subview.setNeedsDisplay()); } @@ -86,10 +89,10 @@ export class View { * * @private */ - setSubviewsNeedDisplay() { - this.subviewsNeedDisplay = true; + _setSubviewsNeedDisplay() { + this._subviewsNeedDisplay = true; if (this.superview) { - this.superview.setSubviewsNeedDisplay(); + this.superview._setSubviewsNeedDisplay(); } } @@ -128,7 +131,7 @@ export class View { * Can be overridden by subclasses. */ desiredSize(): ?Size { - if (this.needsDisplay) { + if (this._needsDisplay) { this.layoutSubviews(); } const frames = this.subviews.map(subview => subview.frame); @@ -175,13 +178,13 @@ export class View { */ displayIfNeeded(context: CanvasRenderingContext2D) { if ( - (this.needsDisplay || this.subviewsNeedDisplay) && + (this._needsDisplay || this._subviewsNeedDisplay) && rectIntersectsRect(this.frame, this.visibleArea) && !sizeIsEmpty(this.visibleArea.size) ) { this.layoutSubviews(); - if (this.needsDisplay) this.needsDisplay = false; - if (this.subviewsNeedDisplay) this.subviewsNeedDisplay = false; + if (this._needsDisplay) this._needsDisplay = false; + if (this._subviewsNeedDisplay) this._subviewsNeedDisplay = false; this.draw(context); } } @@ -201,9 +204,9 @@ export class View { * @see displayIfNeeded */ layoutSubviews() { - const {frame, layouter, subviews, visibleArea} = this; + const {frame, _layouter, subviews, visibleArea} = this; const existingLayout = viewsToLayout(subviews); - const newLayout = layouter(existingLayout, frame); + const newLayout = _layouter(existingLayout, frame); collapseLayoutIntoViews(newLayout); subviews.forEach((subview, subviewIndex) => { From 492ef0329263b564f0525661c79af5f69544149e Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Mon, 3 Aug 2020 08:18:07 +0800 Subject: [PATCH 065/116] [Improve base View][4/n] Write tests for geometry.js (#102) Test Plan * `yarn test`: all new tests pass. 100% coverage of geometry.js. * `yarn lint` * `yarn flow`: no change in errors (test file isn't covered by Flow anyway) --- src/layout/__tests__/geometry-test.js | 265 ++++++++++++++++++++++++++ 1 file changed, 265 insertions(+) create mode 100644 src/layout/__tests__/geometry-test.js diff --git a/src/layout/__tests__/geometry-test.js b/src/layout/__tests__/geometry-test.js new file mode 100644 index 0000000000000..ee7abc5d5d762 --- /dev/null +++ b/src/layout/__tests__/geometry-test.js @@ -0,0 +1,265 @@ +'use strict'; + +import { + pointEqualToPoint, + sizeEqualToSize, + rectEqualToRect, + sizeIsValid, + sizeIsEmpty, + rectIntersectsRect, + rectIntersectionWithRect, + rectContainsPoint, + unionOfRects, +} from '../geometry'; + +describe(pointEqualToPoint, () => { + it('should return true when 2 points have the same values', () => { + expect(pointEqualToPoint({x: 1, y: 1}, {x: 1, y: 1})).toBe(true); + expect(pointEqualToPoint({x: -1, y: 2}, {x: -1, y: 2})).toBe(true); + expect( + pointEqualToPoint({x: 3.14159, y: 0.26535}, {x: 3.14159, y: 0.26535}), + ).toBe(true); + }); + + it('should return false when 2 points have different values', () => { + expect(pointEqualToPoint({x: 1, y: 1}, {x: 1, y: 0})).toBe(false); + expect(pointEqualToPoint({x: -1, y: 2}, {x: 0, y: 1})).toBe(false); + expect( + pointEqualToPoint({x: 3.1416, y: 0.26534}, {x: 3.14159, y: 0.26535}), + ).toBe(false); + }); +}); + +describe(sizeEqualToSize, () => { + it('should return true when 2 sizes have the same values', () => { + expect(sizeEqualToSize({width: 1, height: 1}, {width: 1, height: 1})).toBe( + true, + ); + expect( + sizeEqualToSize({width: -1, height: 2}, {width: -1, height: 2}), + ).toBe(true); + expect( + sizeEqualToSize( + {width: 3.14159, height: 0.26535}, + {width: 3.14159, height: 0.26535}, + ), + ).toBe(true); + }); + + it('should return false when 2 sizes have different values', () => { + expect(sizeEqualToSize({width: 1, height: 1}, {width: 1, height: 0})).toBe( + false, + ); + expect(sizeEqualToSize({width: -1, height: 2}, {width: 0, height: 1})).toBe( + false, + ); + expect( + sizeEqualToSize( + {width: 3.1416, height: 0.26534}, + {width: 3.14159, height: 0.26535}, + ), + ).toBe(false); + }); +}); + +describe(rectEqualToRect, () => { + it('should return true when 2 rects have the same values', () => { + expect( + rectEqualToRect( + {origin: {x: 1, y: 1}, size: {width: 1, height: 1}}, + {origin: {x: 1, y: 1}, size: {width: 1, height: 1}}, + ), + ).toBe(true); + expect( + rectEqualToRect( + {origin: {x: 1, y: 2}, size: {width: 3.14, height: 4}}, + {origin: {x: 1, y: 2}, size: {width: 3.14, height: 4}}, + ), + ).toBe(true); + }); + + it('should return false when 2 rects have different values', () => { + expect( + rectEqualToRect( + {origin: {x: 1, y: 1}, size: {width: 1, height: 1}}, + {origin: {x: 0, y: 1}, size: {width: 1, height: 1}}, + ), + ).toBe(false); + expect( + rectEqualToRect( + {origin: {x: 1, y: 2}, size: {width: 3.14, height: 4}}, + {origin: {x: 1, y: 2}, size: {width: 3.15, height: 4}}, + ), + ).toBe(false); + }); +}); + +describe(sizeIsValid, () => { + it('should return true when the size has non-negative width and height', () => { + expect(sizeIsValid({width: 1, height: 1})).toBe(true); + expect(sizeIsValid({width: 0, height: 0})).toBe(true); + }); + + it('should return false when the size has negative width or height', () => { + expect(sizeIsValid({width: 0, height: -1})).toBe(false); + expect(sizeIsValid({width: -1, height: 0})).toBe(false); + expect(sizeIsValid({width: -1, height: -1})).toBe(false); + }); +}); + +describe(sizeIsEmpty, () => { + it('should return true when the size has negative area', () => { + expect(sizeIsEmpty({width: 1, height: -1})).toBe(true); + expect(sizeIsEmpty({width: -1, height: -1})).toBe(true); + }); + + it('should return true when the size has zero area', () => { + expect(sizeIsEmpty({width: 0, height: 0})).toBe(true); + expect(sizeIsEmpty({width: 0, height: 1})).toBe(true); + expect(sizeIsEmpty({width: 1, height: 0})).toBe(true); + }); + + it('should return false when the size has positive area', () => { + expect(sizeIsEmpty({width: 1, height: 1})).toBe(false); + expect(sizeIsEmpty({width: 2, height: 1})).toBe(false); + }); +}); + +describe(rectIntersectsRect, () => { + it('should return true when 2 rects intersect', () => { + // Rects touch + expect( + rectIntersectsRect( + {origin: {x: 0, y: 0}, size: {width: 1, height: 1}}, + {origin: {x: 1, y: 1}, size: {width: 1, height: 1}}, + ), + ).toEqual(true); + + // Rects overlap + expect( + rectIntersectsRect( + {origin: {x: 0, y: 0}, size: {width: 2, height: 1}}, + {origin: {x: 1, y: -2}, size: {width: 0.5, height: 5}}, + ), + ).toEqual(true); + + // Rects are equal + expect( + rectIntersectsRect( + {origin: {x: 1, y: 2}, size: {width: 3.14, height: 4}}, + {origin: {x: 1, y: 2}, size: {width: 3.14, height: 4}}, + ), + ).toEqual(true); + }); + + it('should return false when 2 rects do not intersect', () => { + expect( + rectIntersectsRect( + {origin: {x: 0, y: 1}, size: {width: 1, height: 1}}, + {origin: {x: 0, y: 10}, size: {width: 1, height: 1}}, + ), + ).toBe(false); + expect( + rectIntersectsRect( + {origin: {x: 1, y: 2}, size: {width: 3.14, height: 4}}, + {origin: {x: -4, y: 2}, size: {width: 3.15, height: 4}}, + ), + ).toBe(false); + }); +}); + +describe(rectIntersectionWithRect, () => { + // NOTE: Undefined behavior if rects do not intersect + + it('should return intersection when 2 rects intersect', () => { + // Rects touch + expect( + rectIntersectionWithRect( + {origin: {x: 0, y: 0}, size: {width: 1, height: 1}}, + {origin: {x: 1, y: 1}, size: {width: 1, height: 1}}, + ), + ).toEqual({origin: {x: 1, y: 1}, size: {width: 0, height: 0}}); + + // Rects overlap + expect( + rectIntersectionWithRect( + {origin: {x: 0, y: 0}, size: {width: 2, height: 1}}, + {origin: {x: 1, y: -2}, size: {width: 0.5, height: 5}}, + ), + ).toEqual({origin: {x: 1, y: 0}, size: {width: 0.5, height: 1}}); + + // Rects are equal + expect( + rectIntersectionWithRect( + {origin: {x: 1, y: 2}, size: {width: 9.24, height: 4}}, + {origin: {x: 1, y: 2}, size: {width: 9.24, height: 4}}, + ), + ).toEqual({origin: {x: 1, y: 2}, size: {width: 9.24, height: 4}}); + }); +}); + +describe(rectContainsPoint, () => { + it("should return true if point is on the rect's boundary", () => { + expect( + rectContainsPoint( + {x: 0, y: 0}, + {origin: {x: 0, y: 0}, size: {width: 1, height: 1}}, + ), + ).toBe(true); + expect( + rectContainsPoint( + {x: 5, y: 0}, + {origin: {x: 0, y: 0}, size: {width: 10, height: 1}}, + ), + ).toBe(true); + expect( + rectContainsPoint( + {x: 1, y: 1}, + {origin: {x: 0, y: 0}, size: {width: 1, height: 1}}, + ), + ).toBe(true); + }); + + it('should return true if point is in rect', () => { + expect( + rectContainsPoint( + {x: 5, y: 50}, + {origin: {x: 0, y: 0}, size: {width: 10, height: 100}}, + ), + ).toBe(true); + }); + + it('should return false if point is not in rect', () => { + expect( + rectContainsPoint( + {x: -1, y: 0}, + {origin: {x: 0, y: 0}, size: {width: 1, height: 1}}, + ), + ).toBe(false); + }); +}); + +describe(unionOfRects, () => { + it('should return zero rect if no rects are provided', () => { + expect(unionOfRects()).toEqual({ + origin: {x: 0, y: 0}, + size: {width: 0, height: 0}, + }); + }); + + it('should return rect if 1 rect is provided', () => { + expect( + unionOfRects({origin: {x: 1, y: 2}, size: {width: 3, height: 4}}), + ).toEqual({origin: {x: 1, y: 2}, size: {width: 3, height: 4}}); + }); + + it('should return union of rects if more than one rect is provided', () => { + expect( + unionOfRects( + {origin: {x: 1, y: 2}, size: {width: 3, height: 4}}, + {origin: {x: 100, y: 200}, size: {width: 3, height: 4}}, + {origin: {x: -10, y: -20}, size: {width: 50, height: 60}}, + ), + ).toEqual({origin: {x: -10, y: -20}, size: {width: 113, height: 224}}); + }); +}); From 726395379ac547f95833bdd992bff5284e68e838 Mon Sep 17 00:00:00 2001 From: Kartik Choudhary Date: Mon, 3 Aug 2020 00:25:54 +0000 Subject: [PATCH 066/116] Refactor tooltip label switch into a util (#103) Co-authored-by: E-Liang Tan --- src/EventTooltip.js | 84 ++++++++++++++++++++------------------------- 1 file changed, 38 insertions(+), 46 deletions(-) diff --git a/src/EventTooltip.js b/src/EventTooltip.js index 300e4039f192c..5a5985e8a046f 100644 --- a/src/EventTooltip.js +++ b/src/EventTooltip.js @@ -38,6 +38,42 @@ function trimComponentName(name) { return name; } +function getReactEventLabel(type) { + switch (type) { + case 'schedule-render': + return 'render scheduled'; + case 'schedule-state-update': + return 'state update scheduled'; + case 'schedule-force-update': + return 'force update scheduled'; + case 'suspense-suspend': + return 'suspended'; + case 'suspense-resolved': + return 'suspense resolved'; + case 'suspense-rejected': + return 'suspense rejected'; + default: + return null; + } +} + +function getReactMeasureLabel(type: string) { + switch (type) { + case 'commit': + return 'commit'; + case 'render-idle': + return 'idle'; + case 'render': + return 'render'; + case 'layout-effects': + return 'layout effects'; + case 'passive-effects': + return 'passive effects'; + default: + return null; + } +} + export default function EventTooltip({data, hoveredEvent, origin}: Props) { const tooltipRef = useSmartTooltip({ mouseX: origin.x, @@ -184,30 +220,7 @@ const TooltipReactEvent = ({ tooltipRef: Return, }) => { const {componentName, componentStack, timestamp, type} = event; - - let label = null; - switch (type) { - case 'schedule-render': - label = 'render scheduled'; - break; - case 'schedule-state-update': - label = 'state update scheduled'; - break; - case 'schedule-force-update': - label = 'force update scheduled'; - break; - case 'suspense-suspend': - label = 'suspended'; - break; - case 'suspense-resolved': - label = 'suspense resolved'; - break; - case 'suspense-rejected': - label = 'suspense rejected'; - break; - default: - break; - } + const label = getReactEventLabel(type); return (
, }) => { const {batchUID, duration, timestamp, type, lanes} = measure; - - let label = null; - switch (type) { - case 'commit': - label = 'commit'; - break; - case 'render-idle': - label = 'idle'; - break; - case 'render': - label = 'render'; - break; - case 'layout-effects': - label = 'layout effects'; - break; - case 'passive-effects': - label = 'passive effects'; - break; - default: - break; - } - + const label = getReactMeasureLabel(type); const [startTime, stopTime] = getBatchRange(batchUID, data); return ( From 636c7aea0d394293d10c1eaa3b274d5dd993e847 Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Tue, 4 Aug 2020 13:07:27 +0800 Subject: [PATCH 067/116] [Resize content][1/n] Break horizontal scrolling area into final-ish hierarchy (#110) Summary --- This PR begins a PR stack that implements the resize of the lanes area. In this PR, the view hierarchy is overhauled to more closely resemble the final one. This is the new view hierarchy: - View (vertically stacked layout) (root view) - HorizontalPanAndZoomView - View (vertically stacked layout) - TimeAxisMarkersView - ReactEventsView - View (vertically stacked layout) (to be replaced with ResizableVerticalSplitView) - HorizontalPanAndZoomView - VerticalScrollView - ReactMeasuresView - HorizontalPanAndZoomView - VerticalScrollView - FlamechartView This PR must be landed with the PRs stacked above it in order not to break master. Test Plan --- * `yarn lint` * `yarn flow`: no errors in changed code * `yarn test` Known issues --- * There are now 3 independent horizontal pan/zoom areas. This is intentional; it'll be fixed in a future PR in this stack. * Flamechart no longer scrolls vertically. This will be fixed in a future PR in this stack. --- src/CanvasPage.js | 104 +++++++++++++++---------- src/layout/HorizontalPanAndZoomView.js | 4 +- src/layout/VerticalScrollView.js | 4 +- 3 files changed, 64 insertions(+), 48 deletions(-) diff --git a/src/CanvasPage.js b/src/CanvasPage.js index 485413cfe2e23..ee9fb7a054df4 100644 --- a/src/CanvasPage.js +++ b/src/CanvasPage.js @@ -14,12 +14,11 @@ import React, { import { HorizontalPanAndZoomView, - VerticalScrollView, Surface, + VerticalScrollView, View, - layeredLayout, - zeroPoint, verticallyStackedLayout, + zeroPoint, } from './layout'; import prettyMilliseconds from 'pretty-ms'; @@ -108,72 +107,93 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) { ] = useState(null); const surfaceRef = useRef(new Surface()); - const flamechartViewRef = useRef(null); - const axisMarkersViewRef = useRef(null); const reactEventsViewRef = useRef(null); const reactMeasuresViewRef = useRef(null); - const rootViewRef = useRef(null); + const flamechartViewRef = useRef(null); useLayoutEffect(() => { + const surface = surfaceRef.current; + const defaultFrame = {origin: zeroPoint, size: {width, height}}; + + // Top content + const axisMarkersView = new TimeAxisMarkersView( - surfaceRef.current, - {origin: zeroPoint, size: {width, height}}, + surface, + defaultFrame, data.duration, ); - axisMarkersViewRef.current = axisMarkersView; - const reactEventsView = new ReactEventsView( - surfaceRef.current, - {origin: zeroPoint, size: {width, height}}, - data, - ); + const reactEventsView = new ReactEventsView(surface, defaultFrame, data); reactEventsViewRef.current = reactEventsView; + const topContentStack = new View( + surface, + defaultFrame, + verticallyStackedLayout, + ); + topContentStack.addSubview(axisMarkersView); + topContentStack.addSubview(reactEventsView); + + const topContentZoomWrapper = new HorizontalPanAndZoomView( + surface, + defaultFrame, + topContentStack, + data.duration, + ); + + // Resizable content + const reactMeasuresView = new ReactMeasuresView( - surfaceRef.current, - {origin: zeroPoint, size: {width, height}}, + surface, + defaultFrame, data, ); reactMeasuresViewRef.current = reactMeasuresView; + const vScrollWrappedReactMeasuresView = new VerticalScrollView( + surface, + defaultFrame, + reactMeasuresView, + ); + const hScrollWrappedReactMeasuresView = new HorizontalPanAndZoomView( + surface, + defaultFrame, + vScrollWrappedReactMeasuresView, + data.duration, + ); const flamechartView = new FlamechartView( - surfaceRef.current, - {origin: zeroPoint, size: {width, height}}, + surface, + defaultFrame, data.flamechart, data.duration, ); flamechartViewRef.current = flamechartView; - const flamechartVScrollWrapper = new VerticalScrollView( - surfaceRef.current, - {origin: zeroPoint, size: {width, height}}, + const vScrollWrappedFlamechartView = new VerticalScrollView( + surface, + defaultFrame, flamechartView, ); - - const stackedZoomables = new View( - surfaceRef.current, - {origin: zeroPoint, size: {width, height}}, - verticallyStackedLayout, - ); - stackedZoomables.addSubview(axisMarkersView); - stackedZoomables.addSubview(reactEventsView); - stackedZoomables.addSubview(reactMeasuresView); - stackedZoomables.addSubview(flamechartVScrollWrapper); - - const contentZoomWrapper = new HorizontalPanAndZoomView( - surfaceRef.current, - {origin: zeroPoint, size: {width, height}}, - stackedZoomables, + const hScrollWrappedFlamechartView = new HorizontalPanAndZoomView( + surface, + defaultFrame, + vScrollWrappedFlamechartView, data.duration, ); - rootViewRef.current = new View( - surfaceRef.current, - {origin: zeroPoint, size: {width, height}}, - layeredLayout, + // TODO: Replace with ResizableSplitView + const resizableContentStack = new View( + surface, + defaultFrame, + verticallyStackedLayout, ); - rootViewRef.current.addSubview(contentZoomWrapper); + resizableContentStack.addSubview(hScrollWrappedReactMeasuresView); + resizableContentStack.addSubview(hScrollWrappedFlamechartView); + + const rootView = new View(surface, defaultFrame, verticallyStackedLayout); + rootView.addSubview(topContentZoomWrapper); + rootView.addSubview(resizableContentStack); - surfaceRef.current.rootView = rootViewRef.current; + surfaceRef.current.rootView = rootView; }, [data, setHoveredEvent]); useLayoutEffect(() => { diff --git a/src/layout/HorizontalPanAndZoomView.js b/src/layout/HorizontalPanAndZoomView.js index 404e7d92552bc..6ceaa564d29e0 100644 --- a/src/layout/HorizontalPanAndZoomView.js +++ b/src/layout/HorizontalPanAndZoomView.js @@ -93,9 +93,7 @@ export class HorizontalPanAndZoomView extends View { } desiredSize() { - // We don't want our superview to fit to our content; we'll fit whatever - // frame we're given. - return null; + return this._contentView.desiredSize(); } /** diff --git a/src/layout/VerticalScrollView.js b/src/layout/VerticalScrollView.js index 71e80ed3cda04..610dd9ef0c8c2 100644 --- a/src/layout/VerticalScrollView.js +++ b/src/layout/VerticalScrollView.js @@ -68,9 +68,7 @@ export class VerticalScrollView extends View { } desiredSize() { - // We don't want our superview to fit to our content; we'll fit whatever - // frame we're given. - return null; + return this._contentView.desiredSize(); } /** From 6c4ad871c4f7fe06fc2a02614971788a94e7b055 Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Tue, 4 Aug 2020 13:12:03 +0800 Subject: [PATCH 068/116] [Resize content][2/n] Implement ResizableSplitView (#107) Summary --- Implements `ResizableSplitView` and uses it to allow resizing of the React measures view. This PR also fixes the last PR's known issue where the flamechart does not scroll vertically. Implements #19. Implements #70. Test Plan --- * `yarn lint` * `yarn flow`: no errors in changed code * `yarn test`: no added tests, but everything still passes * `yarn start`: manual testing: * Hover over resize bar to observe color change * Drag resize bar to resize * Resize bar position is clamped and cannot go offscreen or expand beyond the size of the lanes area * Resize bar remains visible on page resize * Content is independently vertically scrollable There are still 3 independent horizontal pan/zoom areas, a known issue carried over from the last PR in this stack. This will be fixed in the next PR. --- package.json | 1 + src/CanvasPage.js | 20 +- src/layout/ColorView.js | 8 + src/layout/ResizableSplitView.js | 313 +++++++++++++++++++++++++++++++ src/layout/index.js | 1 + src/layout/layouter.js | 44 +++++ 6 files changed, 381 insertions(+), 6 deletions(-) create mode 100644 src/layout/ResizableSplitView.js diff --git a/package.json b/package.json index e50bd2d4a28db..0aa2751ce6ea4 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "d3-hierarchy": "^1.1.9", "lodash.clonedeep": "^4.5.0", "memoize-one": "^5.1.1", + "nullthrows": "^1.1.1", "pretty-ms": "^7.0.0", "react": "^16.13.1", "react-dom": "^16.13.1", diff --git a/src/CanvasPage.js b/src/CanvasPage.js index ee9fb7a054df4..af6f9d63019f8 100644 --- a/src/CanvasPage.js +++ b/src/CanvasPage.js @@ -14,9 +14,12 @@ import React, { import { HorizontalPanAndZoomView, + ResizableSplitView, Surface, VerticalScrollView, View, + createComposedLayout, + lastViewTakesUpRemainingSpaceLayout, verticallyStackedLayout, zeroPoint, } from './layout'; @@ -180,16 +183,21 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) { data.duration, ); - // TODO: Replace with ResizableSplitView - const resizableContentStack = new View( + const resizableContentStack = new ResizableSplitView( surface, defaultFrame, - verticallyStackedLayout, + hScrollWrappedReactMeasuresView, + hScrollWrappedFlamechartView, ); - resizableContentStack.addSubview(hScrollWrappedReactMeasuresView); - resizableContentStack.addSubview(hScrollWrappedFlamechartView); - const rootView = new View(surface, defaultFrame, verticallyStackedLayout); + const rootView = new View( + surface, + defaultFrame, + createComposedLayout( + verticallyStackedLayout, + lastViewTakesUpRemainingSpaceLayout, + ), + ); rootView.addSubview(topContentZoomWrapper); rootView.addSubview(resizableContentStack); diff --git a/src/layout/ColorView.js b/src/layout/ColorView.js index 6c86df0b78524..fd4941c1085c1 100644 --- a/src/layout/ColorView.js +++ b/src/layout/ColorView.js @@ -16,6 +16,14 @@ export class ColorView extends View { this._color = color; } + setColor(color: string) { + if (this._color === color) { + return; + } + this._color = color; + this.setNeedsDisplay(); + } + draw(context: CanvasRenderingContext2D) { const {_color, visibleArea} = this; context.fillStyle = _color; diff --git a/src/layout/ResizableSplitView.js b/src/layout/ResizableSplitView.js new file mode 100644 index 0000000000000..e133ee3d7a988 --- /dev/null +++ b/src/layout/ResizableSplitView.js @@ -0,0 +1,313 @@ +// @flow + +import type { + Interaction, + VerticalPanStartInteraction, + VerticalPanMoveInteraction, + VerticalPanEndInteraction, +} from '../useCanvasInteraction'; +import type {Rect, Size} from './geometry'; + +import nullthrows from 'nullthrows'; +import {Surface} from './Surface'; +import {View} from './View'; +import {rectContainsPoint} from './geometry'; +import {layeredLayout, noopLayout} from './layouter'; +import {ColorView} from './ColorView'; + +type ResizeBarState = 'normal' | 'hovered' | 'dragging'; + +type ResizingState = $ReadOnly<{| + /** Distance between top of resize bar and mouseY */ + cursorOffsetInBarFrame: number, + /** Mouse's vertical coordinates relative to canvas */ + mouseY: number, +|}>; + +type LayoutState = $ReadOnly<{| + /** Resize bar's vertical position relative to resize view's frame.origin.y */ + barOffsetY: number, +|}>; + +// TODO: Deduplicate +function clamp(min: number, max: number, value: number): number { + if (Number.isNaN(min) || Number.isNaN(max) || Number.isNaN(value)) { + throw new Error( + `Clamp was called with NaN. Args: min: ${min}, max: ${max}, value: ${value}.`, + ); + } + return Math.min(max, Math.max(min, value)); +} + +function getColorForBarState(state: ResizeBarState): string { + // Colors obtained from Firefox Profiler + switch (state) { + case 'normal': + return '#ccc'; + case 'hovered': + return '#bbb'; + case 'dragging': + return '#aaa'; + } + throw new Error(`Unknown resize bar state ${state}`); +} + +class ResizeBar extends View { + _intrinsicContentSize: Size = { + width: 0, + height: 5, + }; + + _interactionState: ResizeBarState = 'normal'; + + constructor(surface: Surface, frame: Rect) { + super(surface, frame, layeredLayout); + this.addSubview(new ColorView(surface, frame, '')); + this._updateColor(); + } + + desiredSize() { + return this._intrinsicContentSize; + } + + _getColorView(): ColorView { + return (this.subviews[0]: any); + } + + _updateColor() { + this._getColorView().setColor(getColorForBarState(this._interactionState)); + } + + _setInteractionState(state: ResizeBarState) { + if (this._interactionState === state) { + return; + } + this._interactionState = state; + this._updateColor(); + } + + _handleVerticalPanStart(interaction: VerticalPanStartInteraction) { + const cursorInView = rectContainsPoint( + interaction.payload.location, + this.frame, + ); + if (cursorInView) { + this._setInteractionState('dragging'); + } + } + + _handleVerticalPanMove(interaction: VerticalPanMoveInteraction) { + const cursorInView = rectContainsPoint( + interaction.payload.location, + this.frame, + ); + if (this._interactionState === 'dragging') { + return; + } + this._setInteractionState(cursorInView ? 'hovered' : 'normal'); + } + + _handleVerticalPanEnd(interaction: VerticalPanEndInteraction) { + const cursorInView = rectContainsPoint( + interaction.payload.location, + this.frame, + ); + if (this._interactionState === 'dragging') { + this._setInteractionState(cursorInView ? 'hovered' : 'normal'); + } + } + + handleInteraction(interaction: Interaction) { + switch (interaction.type) { + case 'vertical-pan-start': + this._handleVerticalPanStart(interaction); + return; + case 'vertical-pan-move': + this._handleVerticalPanMove(interaction); + return; + case 'vertical-pan-end': + this._handleVerticalPanEnd(interaction); + return; + } + } +} + +export class ResizableSplitView extends View { + _resizingState: ResizingState | null = null; + _layoutState: LayoutState; + + constructor( + surface: Surface, + frame: Rect, + topSubview: View, + bottomSubview: View, + ) { + super(surface, frame, noopLayout); + + this.addSubview(topSubview); + this.addSubview(new ResizeBar(surface, frame)); + this.addSubview(bottomSubview); + + const topSubviewDesiredSize = topSubview.desiredSize(); + this._layoutState = { + barOffsetY: topSubviewDesiredSize ? topSubviewDesiredSize.height : 0, + }; + } + + _getTopSubview(): View { + return this.subviews[0]; + } + + _getResizeBar(): View { + return this.subviews[1]; + } + + _getBottomSubview(): View { + return this.subviews[2]; + } + + _getResizeBarDesiredSize(): Size { + return nullthrows( + this._getResizeBar().desiredSize(), + 'Resize bar must have desired size', + ); + } + + desiredSize() { + const topSubviewDesiredSize = this._getTopSubview().desiredSize(); + const resizeBarDesiredSize = this._getResizeBarDesiredSize(); + const bottomSubviewDesiredSize = this._getBottomSubview().desiredSize(); + + const topSubviewDesiredWidth = topSubviewDesiredSize + ? topSubviewDesiredSize.width + : 0; + const bottomSubviewDesiredWidth = bottomSubviewDesiredSize + ? bottomSubviewDesiredSize.width + : 0; + + const topSubviewDesiredHeight = topSubviewDesiredSize + ? topSubviewDesiredSize.height + : 0; + const bottomSubviewDesiredHeight = bottomSubviewDesiredSize + ? bottomSubviewDesiredSize.height + : 0; + + return { + width: Math.max( + topSubviewDesiredWidth, + resizeBarDesiredSize.width, + bottomSubviewDesiredWidth, + ), + height: + topSubviewDesiredHeight + + resizeBarDesiredSize.height + + bottomSubviewDesiredHeight, + }; + } + + layoutSubviews() { + this._updateLayoutState(); + this._updateSubviewFrames(); + super.layoutSubviews(); + } + + _updateLayoutState() { + const {frame, visibleArea, _resizingState} = this; + + const resizeBarDesiredSize = this._getResizeBarDesiredSize(); + // Allow bar to travel to bottom of the visible area of this view but no further + const maxPossibleBarOffset = + visibleArea.size.height - resizeBarDesiredSize.height; + const topSubviewDesiredSize = this._getTopSubview().desiredSize(); + const maxBarOffset = topSubviewDesiredSize + ? Math.min(maxPossibleBarOffset, topSubviewDesiredSize.height) + : maxPossibleBarOffset; + + let proposedBarOffsetY = this._layoutState.barOffsetY; + // Update bar offset if dragging bar + if (_resizingState) { + const {mouseY, cursorOffsetInBarFrame} = _resizingState; + proposedBarOffsetY = mouseY - frame.origin.y - cursorOffsetInBarFrame; + } + + this._layoutState = { + ...this._layoutState, + barOffsetY: clamp(0, maxBarOffset, proposedBarOffsetY), + }; + } + + _updateSubviewFrames() { + const { + frame: { + origin: {x, y}, + size: {width, height}, + }, + _layoutState: {barOffsetY}, + } = this; + + const resizeBarDesiredSize = this._getResizeBarDesiredSize(); + + let currentY = y; + + this._getTopSubview().setFrame({ + origin: {x, y: currentY}, + size: {width, height: barOffsetY}, + }); + currentY += this._getTopSubview().frame.size.height; + + this._getResizeBar().setFrame({ + origin: {x, y: currentY}, + size: {width, height: resizeBarDesiredSize.height}, + }); + currentY += this._getResizeBar().frame.size.height; + + this._getBottomSubview().setFrame({ + origin: {x, y: currentY}, + // Fill remaining height + size: {width, height: height + y - currentY}, + }); + } + + _handleVerticalPanStart(interaction: VerticalPanStartInteraction) { + const cursorLocation = interaction.payload.location; + const resizeBarFrame = this._getResizeBar().frame; + if (rectContainsPoint(cursorLocation, resizeBarFrame)) { + const mouseY = cursorLocation.y; + this._resizingState = { + cursorOffsetInBarFrame: mouseY - resizeBarFrame.origin.y, + mouseY, + }; + } + } + + _handleVerticalPanMove(interaction: VerticalPanMoveInteraction) { + const {_resizingState} = this; + if (_resizingState) { + this._resizingState = { + ..._resizingState, + mouseY: interaction.payload.location.y, + }; + this.setNeedsDisplay(); + } + } + + _handleVerticalPanEnd(interaction: VerticalPanEndInteraction) { + if (this._resizingState) { + this._resizingState = null; + } + } + + handleInteraction(interaction: Interaction) { + switch (interaction.type) { + case 'vertical-pan-start': + this._handleVerticalPanStart(interaction); + return; + case 'vertical-pan-move': + this._handleVerticalPanMove(interaction); + return; + case 'vertical-pan-end': + this._handleVerticalPanEnd(interaction); + return; + } + } +} diff --git a/src/layout/index.js b/src/layout/index.js index 76a5cb51ca424..ee378e9749846 100644 --- a/src/layout/index.js +++ b/src/layout/index.js @@ -2,6 +2,7 @@ export * from './ColorView'; export * from './HorizontalPanAndZoomView'; +export * from './ResizableSplitView'; export * from './Surface'; export * from './VerticalScrollView'; export * from './View'; diff --git a/src/layout/layouter.js b/src/layout/layouter.js index 5d62e0e91146a..19a760c9649d5 100644 --- a/src/layout/layouter.js +++ b/src/layout/layouter.js @@ -199,6 +199,50 @@ export const atLeastContainerHeightLayout: Layouter = ( })); }; +/** + * Forces last view to take up the space below the second-last view. + * Intended to be used with a vertical stack layout. + */ +export const lastViewTakesUpRemainingSpaceLayout: Layouter = ( + layout, + containerFrame, +) => { + if (layout.length === 0) { + // Nothing to do + return layout; + } + + if (layout.length === 1) { + // No second-last view; the view should just take up the container height + return containerHeightLayout(layout, containerFrame); + } + + const layoutInfoToPassThrough = layout.slice(0, layout.length - 1); + const secondLastLayoutInfo = + layoutInfoToPassThrough[layoutInfoToPassThrough.length - 1]; + + const remainingHeight = + containerFrame.size.height - + secondLastLayoutInfo.frame.origin.y - + secondLastLayoutInfo.frame.size.height; + const height = Math.max(remainingHeight, 0); // Prevent negative heights + + const lastLayoutInfo = layout[layout.length - 1]; + return [ + ...layoutInfoToPassThrough, + { + ...lastLayoutInfo, + frame: { + origin: lastLayoutInfo.frame.origin, + size: { + width: lastLayoutInfo.frame.size.width, + height, + }, + }, + }, + ]; +}; + /** * Create a layouter that applies each layouter in `layouters` in sequence. */ From 1f0be0a4e2b2fdf1eeb69645dc9a9eeb8ce30b44 Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Tue, 4 Aug 2020 13:14:26 +0800 Subject: [PATCH 069/116] [Resize content][3/n] Sync horizontal pan and zoom states (#108) Summary --- Syncs the state of all 3 horizontal pan and zoom views. Fixes the known issue from the first PR in this stack. Test Plan --- * `yarn lint` * `yarn flow`: no errors in changed code * `yarn test`: no new tests; all existing ones passing * `yarn start`: manual test: panning and zooming on any horizontal pan and zoom view also pans and zooms the others. --- src/CanvasPage.js | 45 ++++++++++++---- src/layout/HorizontalPanAndZoomView.js | 75 +++++++++++++++----------- src/layout/VerticalScrollView.js | 24 ++------- 3 files changed, 83 insertions(+), 61 deletions(-) diff --git a/src/CanvasPage.js b/src/CanvasPage.js index af6f9d63019f8..35d608a81f3e8 100644 --- a/src/CanvasPage.js +++ b/src/CanvasPage.js @@ -1,6 +1,6 @@ // @flow -import type {Point} from './layout'; +import type {Point, HorizontalPanAndZoomViewOnChangeCallback} from './layout'; import {copy} from 'clipboard-js'; import React, { @@ -93,6 +93,17 @@ const copySummary = (data, measure) => { // zoomTo(startTime, stopTime); // }; +const syncedHorizontalPanAndZoomViews: HorizontalPanAndZoomView[] = []; +const syncAllHorizontalPanAndZoomViewStates: HorizontalPanAndZoomViewOnChangeCallback = ( + newState, + view, +) => { + syncedHorizontalPanAndZoomViews.forEach( + syncedView => + view !== syncedView && syncedView.setPanAndZoomState(newState), + ); +}; + type AutoSizedCanvasProps = {| data: ReactProfilerData, height: number, @@ -118,6 +129,12 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) { const surface = surfaceRef.current; const defaultFrame = {origin: zeroPoint, size: {width, height}}; + // Clear synced views + syncedHorizontalPanAndZoomViews.splice( + 0, + syncedHorizontalPanAndZoomViews.length, + ); + // Top content const axisMarkersView = new TimeAxisMarkersView( @@ -137,12 +154,14 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) { topContentStack.addSubview(axisMarkersView); topContentStack.addSubview(reactEventsView); - const topContentZoomWrapper = new HorizontalPanAndZoomView( + const topContentHorizontalPanAndZoomView = new HorizontalPanAndZoomView( surface, defaultFrame, topContentStack, data.duration, + syncAllHorizontalPanAndZoomViewStates, ); + syncedHorizontalPanAndZoomViews.push(topContentHorizontalPanAndZoomView); // Resizable content @@ -152,17 +171,19 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) { data, ); reactMeasuresViewRef.current = reactMeasuresView; - const vScrollWrappedReactMeasuresView = new VerticalScrollView( + const reactMeasuresVerticalScrollView = new VerticalScrollView( surface, defaultFrame, reactMeasuresView, ); - const hScrollWrappedReactMeasuresView = new HorizontalPanAndZoomView( + const reactMeasuresHorizontalPanAndZoomView = new HorizontalPanAndZoomView( surface, defaultFrame, - vScrollWrappedReactMeasuresView, + reactMeasuresVerticalScrollView, data.duration, + syncAllHorizontalPanAndZoomViewStates, ); + syncedHorizontalPanAndZoomViews.push(reactMeasuresHorizontalPanAndZoomView); const flamechartView = new FlamechartView( surface, @@ -171,23 +192,25 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) { data.duration, ); flamechartViewRef.current = flamechartView; - const vScrollWrappedFlamechartView = new VerticalScrollView( + const flamechartVerticalScrollView = new VerticalScrollView( surface, defaultFrame, flamechartView, ); - const hScrollWrappedFlamechartView = new HorizontalPanAndZoomView( + const flamechartHorizontalPanAndZoomView = new HorizontalPanAndZoomView( surface, defaultFrame, - vScrollWrappedFlamechartView, + flamechartVerticalScrollView, data.duration, + syncAllHorizontalPanAndZoomViewStates, ); + syncedHorizontalPanAndZoomViews.push(flamechartHorizontalPanAndZoomView); const resizableContentStack = new ResizableSplitView( surface, defaultFrame, - hScrollWrappedReactMeasuresView, - hScrollWrappedFlamechartView, + reactMeasuresHorizontalPanAndZoomView, + flamechartHorizontalPanAndZoomView, ); const rootView = new View( @@ -198,7 +221,7 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) { lastViewTakesUpRemainingSpaceLayout, ), ); - rootView.addSubview(topContentZoomWrapper); + rootView.addSubview(topContentHorizontalPanAndZoomView); rootView.addSubview(resizableContentStack); surfaceRef.current.rootView = rootView; diff --git a/src/layout/HorizontalPanAndZoomView.js b/src/layout/HorizontalPanAndZoomView.js index 6ceaa564d29e0..6898a62c93c1e 100644 --- a/src/layout/HorizontalPanAndZoomView.js +++ b/src/layout/HorizontalPanAndZoomView.js @@ -21,11 +21,16 @@ import { MOVE_WHEEL_DELTA_THRESHOLD, } from '../canvas/constants'; // TODO: Remove external dependency -type HorizontalPanAndZoomState = {| +type HorizontalPanAndZoomState = $ReadOnly<{| /** Horizontal offset; positive in the left direction */ offsetX: number, zoomLevel: number, -|}; +|}>; + +export type HorizontalPanAndZoomViewOnChangeCallback = ( + state: HorizontalPanAndZoomState, + view: HorizontalPanAndZoomView, +) => void; function panAndZoomStatesAreEqual( state1: HorizontalPanAndZoomState, @@ -62,26 +67,18 @@ export class HorizontalPanAndZoomView extends View { _isPanning = false; - _stateDeriver: ( - state: HorizontalPanAndZoomState, - ) => HorizontalPanAndZoomState = state => state; - - _onStateChange: (state: HorizontalPanAndZoomState) => void = () => {}; + _onStateChange: HorizontalPanAndZoomViewOnChangeCallback = () => {}; constructor( surface: Surface, frame: Rect, contentView: View, intrinsicContentWidth: number, - stateDeriver?: ( - state: HorizontalPanAndZoomState, - ) => HorizontalPanAndZoomState, - onStateChange?: (state: HorizontalPanAndZoomState) => void, + onStateChange?: HorizontalPanAndZoomViewOnChangeCallback, ) { super(surface, frame); this.addSubview(contentView); this._intrinsicContentWidth = intrinsicContentWidth; - if (stateDeriver) this._stateDeriver = stateDeriver; if (onStateChange) this._onStateChange = onStateChange; } @@ -89,7 +86,39 @@ export class HorizontalPanAndZoomView extends View { super.setFrame(newFrame); // Revalidate panAndZoomState - this._updateState(this._panAndZoomState); + this._setStateAndInformCallbacksIfChanged(this._panAndZoomState); + } + + setPanAndZoomState(proposedState: HorizontalPanAndZoomState) { + this._setPanAndZoomState(proposedState); + } + + /** + * Just sets pan and zoom state. Use `_setStateAndInformCallbacksIfChanged` + * if this view's callbacks should also be called. + * + * @returns Whether state was changed + * @private + */ + _setPanAndZoomState(proposedState: HorizontalPanAndZoomState): boolean { + const clampedState = this._clampedProposedState(proposedState); + if (panAndZoomStatesAreEqual(clampedState, this._panAndZoomState)) { + return false; + } + this._panAndZoomState = clampedState; + this.setNeedsDisplay(); + return true; + } + + /** + * @private + */ + _setStateAndInformCallbacksIfChanged( + proposedState: HorizontalPanAndZoomState, + ) { + if (this._setPanAndZoomState(proposedState)) { + this._onStateChange(this._panAndZoomState, this); + } } desiredSize() { @@ -135,7 +164,7 @@ export class HorizontalPanAndZoomView extends View { } const {offsetX} = this._panAndZoomState; const {movementX} = interaction.payload.event; - this._updateState({ + this._setStateAndInformCallbacksIfChanged({ ...this._panAndZoomState, offsetX: offsetX + movementX, }); @@ -166,7 +195,7 @@ export class HorizontalPanAndZoomView extends View { return; } - this._updateState({ + this._setStateAndInformCallbacksIfChanged({ ...this._panAndZoomState, offsetX: this._panAndZoomState.offsetX - deltaX, }); @@ -212,7 +241,7 @@ export class HorizontalPanAndZoomView extends View { offsetX: location.x - newMouseXInFrame, }); - this._updateState(offsetAdjustedState); + this._setStateAndInformCallbacksIfChanged(offsetAdjustedState); } handleInteraction(interaction: Interaction) { @@ -237,20 +266,6 @@ export class HorizontalPanAndZoomView extends View { } } - /** - * @private - */ - _updateState(proposedState: HorizontalPanAndZoomState) { - const clampedState = this._stateDeriver( - this._clampedProposedState(proposedState), - ); - if (!panAndZoomStatesAreEqual(clampedState, this._panAndZoomState)) { - this._panAndZoomState = clampedState; - this._onStateChange(this._panAndZoomState); - this.setNeedsDisplay(); - } - } - /** * @private */ diff --git a/src/layout/VerticalScrollView.js b/src/layout/VerticalScrollView.js index 610dd9ef0c8c2..8fc1d0d786baa 100644 --- a/src/layout/VerticalScrollView.js +++ b/src/layout/VerticalScrollView.js @@ -14,9 +14,9 @@ import {View} from './View'; import {rectContainsPoint} from './geometry'; import {MOVE_WHEEL_DELTA_THRESHOLD} from '../canvas/constants'; // TODO: Remove external dependency -type VerticalScrollState = {| +type VerticalScrollState = $ReadOnly<{| offsetY: number, -|}; +|}>; function scrollStatesAreEqual( state1: VerticalScrollState, @@ -42,22 +42,9 @@ export class VerticalScrollView extends View { _isPanning = false; - _stateDeriver: (state: VerticalScrollState) => VerticalScrollState = state => - state; - - _onStateChange: (state: VerticalScrollState) => void = () => {}; - - constructor( - surface: Surface, - frame: Rect, - contentView: View, - stateDeriver?: (state: VerticalScrollState) => VerticalScrollState, - onStateChange?: (state: VerticalScrollState) => void, - ) { + constructor(surface: Surface, frame: Rect, contentView: View) { super(surface, frame); this.addSubview(contentView); - if (stateDeriver) this._stateDeriver = stateDeriver; - if (onStateChange) this._onStateChange = onStateChange; } setFrame(newFrame: Rect) { @@ -172,12 +159,9 @@ export class VerticalScrollView extends View { * @private */ _updateState(proposedState: VerticalScrollState) { - const clampedState = this._stateDeriver( - this._clampedProposedState(proposedState), - ); + const clampedState = this._clampedProposedState(proposedState); if (!scrollStatesAreEqual(clampedState, this._scrollState)) { this._scrollState = clampedState; - this._onStateChange(this._scrollState); this.setNeedsDisplay(); } } From 2f74a5cda68e6e1903c24959fb0139ab0b20555f Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Tue, 4 Aug 2020 13:20:27 +0800 Subject: [PATCH 070/116] Implement User Timing marks view (#109) Summary --- Implement User Timing marks view as a fixed-height row above our React events. Also adds a tooltip for them. Colors [obtained from Firefox Profiler](https://github.com/firefox-devtools/profiler/blob/c4f68f423c7035a094952311addd0af5bec209e7/src/utils/colors.js#L26-L27) to match Firefox's Marker Chart. The colors aren't the best since they kind of upstage the React events. Resolves #72 iteration 1. This PR does not display User Timing measures due to the complexities of displaying a stack of User Timing measures. I also don't know how to identify a measure's start/end marks, so I'm not able to implement highlighting of related marks. We can create a separate issue for User Timing measures (#72 iteration 3). Test Plan --- * `yarn lint` * `yarn flow`: no type errors in changed code. Also fixed type errors in `EventTooltip`; 24 errors remaining. * `yarn test`: tests for `preprocessData` updated. * `yarn start`: tested with Facebook.com profile --- src/CanvasPage.js | 55 ++++- src/EventTooltip.js | 54 +++-- src/canvas/constants.js | 2 + src/canvas/views/UserTimingMarksView.js | 229 ++++++++++++++++++ src/canvas/views/index.js | 1 + src/types.js | 7 + .../__snapshots__/preprocessData-test.js.snap | 55 +++++ src/util/__tests__/preprocessData-test.js | 38 ++- src/util/preprocessData.js | 22 +- 9 files changed, 418 insertions(+), 45 deletions(-) create mode 100644 src/canvas/views/UserTimingMarksView.js diff --git a/src/CanvasPage.js b/src/CanvasPage.js index 35d608a81f3e8..3590da30414e5 100644 --- a/src/CanvasPage.js +++ b/src/CanvasPage.js @@ -42,6 +42,7 @@ import { ReactEventsView, ReactMeasuresView, TimeAxisMarkersView, + UserTimingMarksView, } from './canvas/views'; type ContextMenuContextData = {| @@ -121,6 +122,7 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) { ] = useState(null); const surfaceRef = useRef(new Surface()); + const userTimingMarksViewRef = useRef(null); const reactEventsViewRef = useRef(null); const reactMeasuresViewRef = useRef(null); const flamechartViewRef = useRef(null); @@ -137,21 +139,32 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) { // Top content - const axisMarkersView = new TimeAxisMarkersView( + const topContentStack = new View( surface, defaultFrame, - data.duration, + verticallyStackedLayout, ); - const reactEventsView = new ReactEventsView(surface, defaultFrame, data); - reactEventsViewRef.current = reactEventsView; - - const topContentStack = new View( + const axisMarkersView = new TimeAxisMarkersView( surface, defaultFrame, - verticallyStackedLayout, + data.duration, ); topContentStack.addSubview(axisMarkersView); + + if (data.otherUserTimingMarks.length > 0) { + const userTimingMarksView = new UserTimingMarksView( + surface, + defaultFrame, + data.otherUserTimingMarks, + data.duration, + ); + userTimingMarksViewRef.current = userTimingMarksView; + topContentStack.addSubview(userTimingMarksView); + } + + const reactEventsView = new ReactEventsView(surface, defaultFrame, data); + reactEventsViewRef.current = reactEventsView; topContentStack.addSubview(reactEventsView); const topContentHorizontalPanAndZoomView = new HorizontalPanAndZoomView( @@ -239,7 +252,8 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) { hoveredEvent && (hoveredEvent.event || hoveredEvent.measure || - hoveredEvent.flamechartStackFrame) + hoveredEvent.flamechartStackFrame || + hoveredEvent.userTimingMark) ) { setMouseLocation({ x: interaction.payload.event.x, @@ -268,11 +282,27 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) { }); useEffect(() => { + const {current: userTimingMarksView} = userTimingMarksViewRef; + if (userTimingMarksView) { + userTimingMarksView.onHover = userTimingMark => { + if (!hoveredEvent || hoveredEvent.userTimingMark !== userTimingMark) { + setHoveredEvent({ + userTimingMark, + event: null, + flamechartStackFrame: null, + measure: null, + data, + }); + } + }; + } + const {current: reactEventsView} = reactEventsViewRef; if (reactEventsView) { reactEventsView.onHover = event => { if (!hoveredEvent || hoveredEvent.event !== event) { setHoveredEvent({ + userTimingMark: null, event, flamechartStackFrame: null, measure: null, @@ -287,6 +317,7 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) { reactMeasuresView.onHover = measure => { if (!hoveredEvent || hoveredEvent.measure !== measure) { setHoveredEvent({ + userTimingMark: null, event: null, flamechartStackFrame: null, measure, @@ -304,6 +335,7 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) { hoveredEvent.flamechartStackFrame !== flamechartStackFrame ) { setHoveredEvent({ + userTimingMark: null, event: null, flamechartStackFrame, measure: null, @@ -321,6 +353,13 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) { ]); useLayoutEffect(() => { + const {current: userTimingMarksView} = userTimingMarksViewRef; + if (userTimingMarksView) { + userTimingMarksView.setHoveredMark( + hoveredEvent ? hoveredEvent.userTimingMark : null, + ); + } + const {current: reactEventsView} = reactEventsViewRef; if (reactEventsView) { reactEventsView.setHoveredEvent(hoveredEvent ? hoveredEvent.event : null); diff --git a/src/EventTooltip.js b/src/EventTooltip.js index 5a5985e8a046f..37ba646da8d92 100644 --- a/src/EventTooltip.js +++ b/src/EventTooltip.js @@ -4,10 +4,11 @@ import type {Point} from './layout'; import type { FlamechartStackFrame, ReactEvent, + ReactHoverContextInfo, ReactMeasure, ReactProfilerData, - ReactHoverContextInfo, Return, + UserTimingMark, } from './types'; import prettyMilliseconds from 'pretty-ms'; @@ -84,7 +85,7 @@ export default function EventTooltip({data, hoveredEvent, origin}: Props) { return null; } - const {event, flamechartStackFrame, measure} = hoveredEvent; + const {event, flamechartStackFrame, measure, userTimingMark} = hoveredEvent; if (event !== null) { switch (event.type) { @@ -150,6 +151,10 @@ export default function EventTooltip({data, hoveredEvent, origin}: Props) { tooltipRef={tooltipRef} /> ); + } else if (userTimingMark !== null) { + return ( + + ); } return null; } @@ -180,13 +185,7 @@ const TooltipFlamechartNode = ({ locationColumn, } = stackFrame; return ( -
+
{formatDuration(duration)} {trimComponentName(name)}
Timestamp:
@@ -223,13 +222,7 @@ const TooltipReactEvent = ({ const label = getReactEventLabel(type); return ( -
+
{componentName && ( {trimComponentName(componentName)} @@ -267,14 +260,7 @@ const TooltipReactMeasure = ({ const [startTime, stopTime] = getBatchRange(batchUID, data); return ( -
+
{formatDuration(duration)} {label}
@@ -290,3 +276,23 @@ const TooltipReactMeasure = ({
); }; + +const TooltipUserTimingMark = ({ + mark, + tooltipRef, +}: { + mark: UserTimingMark, + tooltipRef: Return, +}) => { + const {name, timestamp} = mark; + return ( +
+ {name} +
+
+
Timestamp:
+
{formatTimestamp(timestamp)}
+
+
+ ); +}; diff --git a/src/canvas/constants.js b/src/canvas/constants.js index 4f7c19bd3efb6..d10d138e97902 100644 --- a/src/canvas/constants.js +++ b/src/canvas/constants.js @@ -67,6 +67,8 @@ export const COLORS = Object.freeze({ PRIORITY_BACKGROUND: '#ededf0', PRIORITY_BORDER: '#d7d7db', PRIORITY_LABEL: '#272727', + USER_TIMING: '#45a1ff', + USER_TIMING_HOVER: '#0a84ff', REACT_IDLE: '#edf6ff', REACT_IDLE_SELECTED: '#EDF6FF', REACT_IDLE_HOVER: '#EDF6FF', diff --git a/src/canvas/views/UserTimingMarksView.js b/src/canvas/views/UserTimingMarksView.js new file mode 100644 index 0000000000000..8e431c18d504d --- /dev/null +++ b/src/canvas/views/UserTimingMarksView.js @@ -0,0 +1,229 @@ +// @flow + +import type {Interaction, HoverInteraction} from '../../useCanvasInteraction'; +import type {UserTimingMark} from '../../types'; +import type {Rect, Size} from '../../layout'; + +import { + positioningScaleFactor, + timestampToPosition, + positionToTimestamp, + widthToDuration, +} from '../canvasUtils'; +import { + View, + Surface, + rectContainsPoint, + rectIntersectsRect, + rectIntersectionWithRect, +} from '../../layout'; +import { + COLORS, + EVENT_ROW_HEIGHT_FIXED, + REACT_EVENT_ROW_PADDING, + REACT_EVENT_SIZE, + REACT_WORK_BORDER_SIZE, +} from '../constants'; + +// COMBAK: use this viewA + +export class UserTimingMarksView extends View { + _marks: UserTimingMark[]; + _intrinsicSize: Size; + + _hoveredMark: UserTimingMark | null = null; + onHover: ((mark: UserTimingMark | null) => void) | null = null; + + constructor( + surface: Surface, + frame: Rect, + marks: UserTimingMark[], + duration: number, + ) { + super(surface, frame); + this._marks = marks; + + this._intrinsicSize = { + width: duration, + height: EVENT_ROW_HEIGHT_FIXED, + }; + } + + desiredSize() { + return this._intrinsicSize; + } + + setHoveredMark(hoveredMark: UserTimingMark | null) { + if (this._hoveredMark === hoveredMark) { + return; + } + this._hoveredMark = hoveredMark; + this.setNeedsDisplay(); + } + + /** + * Draw a single `UserTimingMark` as a circle in the canvas. + */ + _drawSingleMark( + context: CanvasRenderingContext2D, + rect: Rect, + mark: UserTimingMark, + baseY: number, + scaleFactor: number, + showHoverHighlight: boolean, + ) { + const {frame} = this; + const {timestamp} = mark; + + const x = timestampToPosition(timestamp, scaleFactor, frame); + const radius = REACT_EVENT_SIZE / 2; + const markRect: Rect = { + origin: { + x: x - radius, + y: baseY, + }, + size: {width: REACT_EVENT_SIZE, height: REACT_EVENT_SIZE}, + }; + if (!rectIntersectsRect(markRect, rect)) { + return; // Not in view + } + + // TODO: Use blue color from Firefox + const fillStyle = showHoverHighlight + ? COLORS.USER_TIMING_HOVER + : COLORS.USER_TIMING; + + if (fillStyle !== null) { + const y = markRect.origin.y + radius; + + context.beginPath(); + context.fillStyle = fillStyle; + context.arc(x, y, radius, 0, 2 * Math.PI); + context.fill(); + } + } + + draw(context: CanvasRenderingContext2D) { + const {frame, _marks, _hoveredMark, visibleArea} = this; + + context.fillStyle = COLORS.BACKGROUND; + context.fillRect( + visibleArea.origin.x, + visibleArea.origin.y, + visibleArea.size.width, + visibleArea.size.height, + ); + + // Draw marks + const baseY = frame.origin.y + REACT_EVENT_ROW_PADDING; + const scaleFactor = positioningScaleFactor( + this._intrinsicSize.width, + frame, + ); + + _marks.forEach(mark => { + if (mark === _hoveredMark) { + return; + } + this._drawSingleMark( + context, + visibleArea, + mark, + baseY, + scaleFactor, + false, + ); + }); + + // Draw the hovered and/or selected items on top so they stand out. + // This is helpful if there are multiple (overlapping) items close to each other. + if (_hoveredMark !== null) { + this._drawSingleMark( + context, + visibleArea, + _hoveredMark, + baseY, + scaleFactor, + true, + ); + } + + // Render bottom border. + // Propose border rect, check if intersects with `rect`, draw intersection. + const borderFrame: Rect = { + origin: { + x: frame.origin.x, + y: frame.origin.y + EVENT_ROW_HEIGHT_FIXED - REACT_WORK_BORDER_SIZE, + }, + size: { + width: frame.size.width, + height: REACT_WORK_BORDER_SIZE, + }, + }; + if (rectIntersectsRect(borderFrame, visibleArea)) { + const borderDrawableRect = rectIntersectionWithRect( + borderFrame, + visibleArea, + ); + context.fillStyle = COLORS.PRIORITY_BORDER; + context.fillRect( + borderDrawableRect.origin.x, + borderDrawableRect.origin.y, + borderDrawableRect.size.width, + borderDrawableRect.size.height, + ); + } + } + + /** + * @private + */ + _handleHover(interaction: HoverInteraction) { + const {frame, onHover, visibleArea} = this; + if (!onHover) { + return; + } + + const {location} = interaction.payload; + if (!rectContainsPoint(location, visibleArea)) { + onHover(null); + return; + } + + const {_marks} = this; + const scaleFactor = positioningScaleFactor( + this._intrinsicSize.width, + frame, + ); + const hoverTimestamp = positionToTimestamp(location.x, scaleFactor, frame); + const markTimestampAllowance = widthToDuration( + REACT_EVENT_SIZE / 2, + scaleFactor, + ); + + // Because data ranges may overlap, we want to find the last intersecting item. + // This will always be the one on "top" (the one the user is hovering over). + for (let index = _marks.length - 1; index >= 0; index--) { + const mark = _marks[index]; + const {timestamp} = mark; + + if ( + timestamp - markTimestampAllowance <= hoverTimestamp && + hoverTimestamp <= timestamp + markTimestampAllowance + ) { + onHover(mark); + return; + } + } + + onHover(null); + } + + handleInteraction(interaction: Interaction) { + switch (interaction.type) { + case 'hover': + this._handleHover(interaction); + break; + } + } +} diff --git a/src/canvas/views/index.js b/src/canvas/views/index.js index 306e396f2f834..de3ee38c05539 100644 --- a/src/canvas/views/index.js +++ b/src/canvas/views/index.js @@ -4,3 +4,4 @@ export * from './FlamechartView'; export * from './ReactEventsView'; export * from './ReactMeasuresView'; export * from './TimeAxisMarkersView'; +export * from './UserTimingMarksView'; diff --git a/src/types.js b/src/types.js index 05c72016f0f40..708b6bc4bba88 100644 --- a/src/types.js +++ b/src/types.js @@ -97,6 +97,11 @@ export type FlamechartStackFrame = {| locationColumn?: number, |}; +export type UserTimingMark = {| + name: string, + timestamp: Milliseconds, +|}; + /** * A "layer" of stack frames in the profiler UI, i.e. all stack frames of the * same depth across all stack traces. Displayed as a flamechart row in the UI. @@ -111,6 +116,7 @@ export type ReactProfilerData = {| events: ReactEvent[], measures: ReactMeasure[], flamechart: Flamechart, + otherUserTimingMarks: UserTimingMark[], |}; export type ReactHoverContextInfo = {| @@ -118,4 +124,5 @@ export type ReactHoverContextInfo = {| measure: ReactMeasure | null, data: $ReadOnly | null, flamechartStackFrame: FlamechartStackFrame | null, + userTimingMark: UserTimingMark | null, |}; diff --git a/src/util/__tests__/__snapshots__/preprocessData-test.js.snap b/src/util/__tests__/__snapshots__/preprocessData-test.js.snap index 89993c69a8a0b..4055b6d45e239 100644 --- a/src/util/__tests__/__snapshots__/preprocessData-test.js.snap +++ b/src/util/__tests__/__snapshots__/preprocessData-test.js.snap @@ -1256,6 +1256,60 @@ Object { "type": "layout-effects", }, ], + "otherUserTimingMarks": Array [ + Object { + "name": "navigationStart", + "timestamp": -29.357, + }, + Object { + "name": "fetchStart", + "timestamp": -26.92, + }, + Object { + "name": "requestStart", + "timestamp": -21.171, + }, + Object { + "name": "responseEnd", + "timestamp": -15.655, + }, + Object { + "name": "unloadEventStart", + "timestamp": -0.74, + }, + Object { + "name": "unloadEventEnd", + "timestamp": 39.608, + }, + Object { + "name": "requestStart", + "timestamp": 107.649, + }, + Object { + "name": "requestStart", + "timestamp": 108.385, + }, + Object { + "name": "loadEventStart", + "timestamp": 307.056, + }, + Object { + "name": "loadEventEnd", + "timestamp": 308.242, + }, + Object { + "name": "requestStart", + "timestamp": 341.329, + }, + Object { + "name": "requestStart", + "timestamp": 344.02, + }, + Object { + "name": "requestStart", + "timestamp": 387.585, + }, + ], "startTime": 8993778496, } `; @@ -1320,6 +1374,7 @@ Object { "type": "layout-effects", }, ], + "otherUserTimingMarks": Array [], "startTime": 40806924876, } `; diff --git a/src/util/__tests__/preprocessData-test.js b/src/util/__tests__/preprocessData-test.js index e4a3ebac12c85..3dd79054a8a90 100644 --- a/src/util/__tests__/preprocessData-test.js +++ b/src/util/__tests__/preprocessData-test.js @@ -81,19 +81,10 @@ describe(preprocessData, () => { events: [], measures: [], flamechart: [], + otherUserTimingMarks: [], }); }); - it('should throw if unrecognized React mark is encountered', () => { - expect(() => - // prettier-ignore - preprocessData([ - {"args":{"data":{"startTime":8993778496}},"cat":"disabled-by-default-v8.cpu_profiler","id":"0x1","name":"Profile","ph":"P","pid":9312,"tid":10252,"ts":8993778520,"tts":1614266}, - {"args":{"data":{"navigationId":"E082C30FBDA3ACEE0E7B5FD75F8B7F0D"}},"cat":"blink.user_timing","name":"--there-are-four-lights","ph":"R","pid":17232,"tid":13628,"ts":264686513020,"tts":4082554}, - ]), - ).toThrow(); - }); - it('should throw if events and measures are incomplete', () => { const error = jest.spyOn(console, 'error'); // prettier-ignore @@ -325,5 +316,32 @@ describe(preprocessData, () => { ).toMatchSnapshot(); }); + it('should populate other user timing marks', () => { + expect( + // prettier-ignore + preprocessData([ + {"args":{"data":{"startTime":8993778496}},"cat":"disabled-by-default-v8.cpu_profiler","id":"0x1","name":"Profile","ph":"P","pid":9312,"tid":10252,"ts":8993778520,"tts":1614266}, + {"args":{"data":{"navigationId":"E082C30FBDA3ACEE0E7B5FD75F8B7F0D"}},"cat":"blink.user_timing","name":"--a-mark-that-looks-like-one-of-ours","ph":"R","pid":17232,"tid":13628,"ts":264686513020,"tts":4082554}, + {"args":{"data":{"navigationId":"E082C30FBDA3ACEE0E7B5FD75F8B7F0D"}},"cat":"blink.user_timing","name":"Some other mark","ph":"R","pid":17232,"tid":13628,"ts":264686513020,"tts":4082554}, + {"args":{},"cat":"blink.user_timing","id":"0xcdf75f7c","name":"VCWithoutImage: root","ph":"n","pid":55132,"scope":"blink.user_timing","tid":775,"ts":458734963394}, + ]).otherUserTimingMarks, + ).toMatchInlineSnapshot(` + Array [ + Object { + "name": "Some other mark", + "timestamp": 255692734.524, + }, + Object { + "name": "--a-mark-that-looks-like-one-of-ours", + "timestamp": 255692734.524, + }, + Object { + "name": "VCWithoutImage: root", + "timestamp": 449741184.898, + }, + ] + `); + }); + // TODO: Add test for flamechart parsing }); diff --git a/src/util/preprocessData.js b/src/util/preprocessData.js index 3cfc126212a9e..9d46a36134756 100644 --- a/src/util/preprocessData.js +++ b/src/util/preprocessData.js @@ -146,8 +146,8 @@ function processTimelineEvent( /** Intermediate processor state. May be mutated. */ state: ProcessorState, ) { - const {cat, name, ts} = event; - if (cat !== 'blink.user_timing' || !name.startsWith('--')) { + const {cat, name, ts, ph} = event; + if (cat !== 'blink.user_timing') { return; } @@ -342,10 +342,25 @@ function processTimelineEvent( ); } // eslint-disable-line brace-style + // Other user timing marks/measures + else if (ph === 'R' || ph === 'n') { + // User Timing mark + currentProfilerData.otherUserTimingMarks.push({ + name, + timestamp: startTime, + }); + } else if (ph === 'b') { + // TODO: Begin user timing measure (#112) + } else if (ph === 'e') { + // TODO: End user timing measure (#112) + } // eslint-disable-line brace-style + // Unrecognized event else { throw new Error( - `Unrecognized event ${name}! This is likely a bug in this profiler tool.`, + `Unrecognized event ${JSON.stringify( + event, + )}! This is likely a bug in this profiler tool.`, ); } } @@ -386,6 +401,7 @@ export default function preprocessData( events: [], measures: [], flamechart, + otherUserTimingMarks: [], }; // Sort `timeline`. JSON Array Format trace events need not be ordered. See: From cb50ff8a773816e153d0b1245d9d6064d72a30f9 Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Tue, 4 Aug 2020 13:25:38 +0800 Subject: [PATCH 071/116] Highlight React events with the same wakeable ID (#111) Summary --- Resolves #44. Intended to highlight all related React events. However, it looks like separate promises can have the same wakeable ID, which is a bit strange. TODO --- * Ensure that we are correctly understanding wakeable IDs, i.e. that a unique resource/promise is a unique wakeable. * Check if `unstable_createResource` caches promises. Test Plan --- * `yarn lint` * `yarn flow`: no errors in changed code --- src/canvas/views/ReactEventsView.js | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/canvas/views/ReactEventsView.js b/src/canvas/views/ReactEventsView.js index 4b3f1c55b99a3..5329dd2c959f9 100644 --- a/src/canvas/views/ReactEventsView.js +++ b/src/canvas/views/ReactEventsView.js @@ -25,6 +25,14 @@ import { REACT_WORK_BORDER_SIZE, } from '../constants'; +function isSuspenseEvent(event: ReactEvent): boolean %checks { + return ( + event.type === 'suspense-suspend' || + event.type === 'suspense-resolved' || + event.type === 'suspense-rejected' + ); +} + export class ReactEventsView extends View { _profilerData: ReactProfilerData; _intrinsicSize: Size; @@ -142,8 +150,17 @@ export class ReactEventsView extends View { frame, ); + const highlightedEvents: ReactEvent[] = []; + events.forEach(event => { - if (event === _hoveredEvent) { + if ( + event === _hoveredEvent || + (_hoveredEvent && + isSuspenseEvent(event) && + isSuspenseEvent(_hoveredEvent) && + event.id === _hoveredEvent.id) + ) { + highlightedEvents.push(event); return; } this._drawSingleReactEvent( @@ -156,18 +173,18 @@ export class ReactEventsView extends View { ); }); - // Draw the hovered and/or selected items on top so they stand out. + // Draw the highlighted items on top so they stand out. // This is helpful if there are multiple (overlapping) items close to each other. - if (_hoveredEvent !== null) { + highlightedEvents.forEach(event => { this._drawSingleReactEvent( context, visibleArea, - _hoveredEvent, + event, baseY, scaleFactor, true, ); - } + }); // Render bottom border. // Propose border rect, check if intersects with `rect`, draw intersection. From 371ddf5f174143e8a4254fb925bc4e5576117fdc Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Wed, 5 Aug 2020 20:54:05 +0800 Subject: [PATCH 072/116] Improve Firefox scrolling performance (#114) --- src/canvas/views/FlamechartView.js | 2 ++ src/useCanvasInteraction.js | 19 ++++++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/canvas/views/FlamechartView.js b/src/canvas/views/FlamechartView.js index 6c21e27c786b0..bb18018edf839 100644 --- a/src/canvas/views/FlamechartView.js +++ b/src/canvas/views/FlamechartView.js @@ -184,12 +184,14 @@ class FlamechartStackLayerView extends View { ); if (textOverflowsViewableArea) { context.save(); + context.beginPath(); context.rect( drawableRect.origin.x, drawableRect.origin.y, drawableRect.size.width, drawableRect.size.height, ); + context.closePath(); context.clip(); } diff --git a/src/useCanvasInteraction.js b/src/useCanvasInteraction.js index 0b2136faa952a..1cb5c37b260ff 100644 --- a/src/useCanvasInteraction.js +++ b/src/useCanvasInteraction.js @@ -95,6 +95,23 @@ export type Interaction = | WheelWithControlInteraction | WheelWithMetaInteraction; +let canvasBoundingRectCache = null; +function cacheFirstGetCanvasBoundingRect(canvas) { + if ( + canvasBoundingRectCache && + canvas.width === canvasBoundingRectCache.width && + canvas.height === canvasBoundingRectCache.height + ) { + return canvasBoundingRectCache.rect; + } + canvasBoundingRectCache = { + width: canvas.width, + height: canvas.height, + rect: canvas.getBoundingClientRect(), + }; + return canvasBoundingRectCache.rect; +} + export function useCanvasInteraction( canvasRef: {|current: HTMLCanvasElement | null|}, interactor: (interaction: Interaction) => void, @@ -106,7 +123,7 @@ export function useCanvasInteraction( if (!canvas) { return localCoordinates; } - const canvasRect = canvas.getBoundingClientRect(); + const canvasRect = cacheFirstGetCanvasBoundingRect(canvas); return { x: localCoordinates.x - canvasRect.left, y: localCoordinates.y - canvasRect.top, From a115c5889e7a43d152c3baea0bae56ee3a8eaf03 Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Wed, 5 Aug 2020 20:57:04 +0800 Subject: [PATCH 073/116] Codemod pan/hover interactions -> mouse interactions (#115) --- src/canvas/views/FlamechartView.js | 17 ++--- src/canvas/views/ReactEventsView.js | 11 ++-- src/canvas/views/ReactMeasuresView.js | 11 ++-- src/canvas/views/UserTimingMarksView.js | 11 ++-- src/layout/HorizontalPanAndZoomView.js | 24 +++---- src/layout/ResizableSplitView.js | 42 ++++++------- src/layout/VerticalScrollView.js | 24 +++---- src/useCanvasInteraction.js | 84 ++++--------------------- 8 files changed, 88 insertions(+), 136 deletions(-) diff --git a/src/canvas/views/FlamechartView.js b/src/canvas/views/FlamechartView.js index bb18018edf839..585d7f589b670 100644 --- a/src/canvas/views/FlamechartView.js +++ b/src/canvas/views/FlamechartView.js @@ -1,6 +1,9 @@ // @flow -import type {Interaction, HoverInteraction} from '../../useCanvasInteraction'; +import type { + Interaction, + MouseMoveInteraction, +} from '../../useCanvasInteraction'; import type { Flamechart, FlamechartStackFrame, @@ -212,7 +215,7 @@ class FlamechartStackLayerView extends View { /** * @private */ - _handleHover(interaction: HoverInteraction) { + _handleMouseMove(interaction: MouseMoveInteraction) { const {_stackLayer, frame, _intrinsicSize, _onHover, visibleArea} = this; const {location} = interaction.payload; if (!_onHover || !rectContainsPoint(location, visibleArea)) { @@ -247,8 +250,8 @@ class FlamechartStackLayerView extends View { handleInteraction(interaction: Interaction) { switch (interaction.type) { - case 'hover': - this._handleHover(interaction); + case 'mousemove': + this._handleMouseMove(interaction); break; } } @@ -327,7 +330,7 @@ export class FlamechartView extends View { /** * @private */ - _handleHover(interaction: HoverInteraction) { + _handleMouseMove(interaction: MouseMoveInteraction) { const {_onHover, visibleArea} = this; if (!_onHover) { return; @@ -342,8 +345,8 @@ export class FlamechartView extends View { handleInteraction(interaction: Interaction) { switch (interaction.type) { - case 'hover': - this._handleHover(interaction); + case 'mousemove': + this._handleMouseMove(interaction); break; } } diff --git a/src/canvas/views/ReactEventsView.js b/src/canvas/views/ReactEventsView.js index 5329dd2c959f9..e73c837490d09 100644 --- a/src/canvas/views/ReactEventsView.js +++ b/src/canvas/views/ReactEventsView.js @@ -1,6 +1,9 @@ // @flow -import type {Interaction, HoverInteraction} from '../../useCanvasInteraction'; +import type { + Interaction, + MouseMoveInteraction, +} from '../../useCanvasInteraction'; import type {ReactEvent, ReactProfilerData} from '../../types'; import type {Rect, Size} from '../../layout'; @@ -216,7 +219,7 @@ export class ReactEventsView extends View { /** * @private */ - _handleHover(interaction: HoverInteraction) { + _handleMouseMove(interaction: MouseMoveInteraction) { const {frame, onHover, visibleArea} = this; if (!onHover) { return; @@ -261,8 +264,8 @@ export class ReactEventsView extends View { handleInteraction(interaction: Interaction) { switch (interaction.type) { - case 'hover': - this._handleHover(interaction); + case 'mousemove': + this._handleMouseMove(interaction); break; } } diff --git a/src/canvas/views/ReactMeasuresView.js b/src/canvas/views/ReactMeasuresView.js index 1419d3fb705b7..317e9a3647aca 100644 --- a/src/canvas/views/ReactMeasuresView.js +++ b/src/canvas/views/ReactMeasuresView.js @@ -1,6 +1,9 @@ // @flow -import type {Interaction, HoverInteraction} from '../../useCanvasInteraction'; +import type { + Interaction, + MouseMoveInteraction, +} from '../../useCanvasInteraction'; import type {ReactLane, ReactMeasure, ReactProfilerData} from '../../types'; import type {Rect, Size} from '../../layout'; @@ -239,7 +242,7 @@ export class ReactMeasuresView extends View { /** * @private */ - _handleHover(interaction: HoverInteraction) { + _handleMouseMove(interaction: MouseMoveInteraction) { const { frame, _intrinsicSize, @@ -299,8 +302,8 @@ export class ReactMeasuresView extends View { handleInteraction(interaction: Interaction) { switch (interaction.type) { - case 'hover': - this._handleHover(interaction); + case 'mousemove': + this._handleMouseMove(interaction); break; } } diff --git a/src/canvas/views/UserTimingMarksView.js b/src/canvas/views/UserTimingMarksView.js index 8e431c18d504d..0cf3ad6099c8e 100644 --- a/src/canvas/views/UserTimingMarksView.js +++ b/src/canvas/views/UserTimingMarksView.js @@ -1,6 +1,9 @@ // @flow -import type {Interaction, HoverInteraction} from '../../useCanvasInteraction'; +import type { + Interaction, + MouseMoveInteraction, +} from '../../useCanvasInteraction'; import type {UserTimingMark} from '../../types'; import type {Rect, Size} from '../../layout'; @@ -178,7 +181,7 @@ export class UserTimingMarksView extends View { /** * @private */ - _handleHover(interaction: HoverInteraction) { + _handleMouseMove(interaction: MouseMoveInteraction) { const {frame, onHover, visibleArea} = this; if (!onHover) { return; @@ -221,8 +224,8 @@ export class UserTimingMarksView extends View { handleInteraction(interaction: Interaction) { switch (interaction.type) { - case 'hover': - this._handleHover(interaction); + case 'mousemove': + this._handleMouseMove(interaction); break; } } diff --git a/src/layout/HorizontalPanAndZoomView.js b/src/layout/HorizontalPanAndZoomView.js index 6898a62c93c1e..e8d04f1b77935 100644 --- a/src/layout/HorizontalPanAndZoomView.js +++ b/src/layout/HorizontalPanAndZoomView.js @@ -2,9 +2,9 @@ import type { Interaction, - HorizontalPanStartInteraction, - HorizontalPanMoveInteraction, - HorizontalPanEndInteraction, + MouseDownInteraction, + MouseMoveInteraction, + MouseUpInteraction, WheelPlainInteraction, WheelWithShiftInteraction, WheelWithControlInteraction, @@ -152,13 +152,13 @@ export class HorizontalPanAndZoomView extends View { super.layoutSubviews(); } - _handleHorizontalPanStart(interaction: HorizontalPanStartInteraction) { + _handleMouseDown(interaction: MouseDownInteraction) { if (rectContainsPoint(interaction.payload.location, this.frame)) { this._isPanning = true; } } - _handleHorizontalPanMove(interaction: HorizontalPanMoveInteraction) { + _handleMouseMove(interaction: MouseMoveInteraction) { if (!this._isPanning) { return; } @@ -170,7 +170,7 @@ export class HorizontalPanAndZoomView extends View { }); } - _handleHorizontalPanEnd(interaction: HorizontalPanEndInteraction) { + _handleMouseUp(interaction: MouseUpInteraction) { if (this._isPanning) { this._isPanning = false; } @@ -246,14 +246,14 @@ export class HorizontalPanAndZoomView extends View { handleInteraction(interaction: Interaction) { switch (interaction.type) { - case 'horizontal-pan-start': - this._handleHorizontalPanStart(interaction); + case 'mousedown': + this._handleMouseDown(interaction); break; - case 'horizontal-pan-move': - this._handleHorizontalPanMove(interaction); + case 'mousemove': + this._handleMouseMove(interaction); break; - case 'horizontal-pan-end': - this._handleHorizontalPanEnd(interaction); + case 'mouseup': + this._handleMouseUp(interaction); break; case 'wheel-plain': this._handleWheelPlain(interaction); diff --git a/src/layout/ResizableSplitView.js b/src/layout/ResizableSplitView.js index e133ee3d7a988..e06c5e4b8155f 100644 --- a/src/layout/ResizableSplitView.js +++ b/src/layout/ResizableSplitView.js @@ -2,9 +2,9 @@ import type { Interaction, - VerticalPanStartInteraction, - VerticalPanMoveInteraction, - VerticalPanEndInteraction, + MouseDownInteraction, + MouseMoveInteraction, + MouseUpInteraction, } from '../useCanvasInteraction'; import type {Rect, Size} from './geometry'; @@ -86,7 +86,7 @@ class ResizeBar extends View { this._updateColor(); } - _handleVerticalPanStart(interaction: VerticalPanStartInteraction) { + _handleMouseDown(interaction: MouseDownInteraction) { const cursorInView = rectContainsPoint( interaction.payload.location, this.frame, @@ -96,7 +96,7 @@ class ResizeBar extends View { } } - _handleVerticalPanMove(interaction: VerticalPanMoveInteraction) { + _handleMouseMove(interaction: MouseMoveInteraction) { const cursorInView = rectContainsPoint( interaction.payload.location, this.frame, @@ -107,7 +107,7 @@ class ResizeBar extends View { this._setInteractionState(cursorInView ? 'hovered' : 'normal'); } - _handleVerticalPanEnd(interaction: VerticalPanEndInteraction) { + _handleMouseUp(interaction: MouseUpInteraction) { const cursorInView = rectContainsPoint( interaction.payload.location, this.frame, @@ -119,14 +119,14 @@ class ResizeBar extends View { handleInteraction(interaction: Interaction) { switch (interaction.type) { - case 'vertical-pan-start': - this._handleVerticalPanStart(interaction); + case 'mousedown': + this._handleMouseDown(interaction); return; - case 'vertical-pan-move': - this._handleVerticalPanMove(interaction); + case 'mousemove': + this._handleMouseMove(interaction); return; - case 'vertical-pan-end': - this._handleVerticalPanEnd(interaction); + case 'mouseup': + this._handleMouseUp(interaction); return; } } @@ -268,7 +268,7 @@ export class ResizableSplitView extends View { }); } - _handleVerticalPanStart(interaction: VerticalPanStartInteraction) { + _handleMouseDown(interaction: MouseDownInteraction) { const cursorLocation = interaction.payload.location; const resizeBarFrame = this._getResizeBar().frame; if (rectContainsPoint(cursorLocation, resizeBarFrame)) { @@ -280,7 +280,7 @@ export class ResizableSplitView extends View { } } - _handleVerticalPanMove(interaction: VerticalPanMoveInteraction) { + _handleMouseMove(interaction: MouseMoveInteraction) { const {_resizingState} = this; if (_resizingState) { this._resizingState = { @@ -291,7 +291,7 @@ export class ResizableSplitView extends View { } } - _handleVerticalPanEnd(interaction: VerticalPanEndInteraction) { + _handleMouseUp(interaction: MouseUpInteraction) { if (this._resizingState) { this._resizingState = null; } @@ -299,14 +299,14 @@ export class ResizableSplitView extends View { handleInteraction(interaction: Interaction) { switch (interaction.type) { - case 'vertical-pan-start': - this._handleVerticalPanStart(interaction); + case 'mousedown': + this._handleMouseDown(interaction); return; - case 'vertical-pan-move': - this._handleVerticalPanMove(interaction); + case 'mousemove': + this._handleMouseMove(interaction); return; - case 'vertical-pan-end': - this._handleVerticalPanEnd(interaction); + case 'mouseup': + this._handleMouseUp(interaction); return; } } diff --git a/src/layout/VerticalScrollView.js b/src/layout/VerticalScrollView.js index 8fc1d0d786baa..78baa9ef0b09b 100644 --- a/src/layout/VerticalScrollView.js +++ b/src/layout/VerticalScrollView.js @@ -2,9 +2,9 @@ import type { Interaction, - VerticalPanStartInteraction, - VerticalPanMoveInteraction, - VerticalPanEndInteraction, + MouseDownInteraction, + MouseMoveInteraction, + MouseUpInteraction, WheelPlainInteraction, } from '../useCanvasInteraction'; import type {Rect} from './geometry'; @@ -89,13 +89,13 @@ export class VerticalScrollView extends View { super.layoutSubviews(); } - _handleVerticalPanStart(interaction: VerticalPanStartInteraction) { + _handleMouseDown(interaction: MouseDownInteraction) { if (rectContainsPoint(interaction.payload.location, this.frame)) { this._isPanning = true; } } - _handleVerticalPanMove(interaction: VerticalPanMoveInteraction) { + _handleMouseMove(interaction: MouseMoveInteraction) { if (!this._isPanning) { return; } @@ -107,7 +107,7 @@ export class VerticalScrollView extends View { }); } - _handleVerticalPanEnd(interaction: VerticalPanEndInteraction) { + _handleMouseUp(interaction: MouseUpInteraction) { if (this._isPanning) { this._isPanning = false; } @@ -140,14 +140,14 @@ export class VerticalScrollView extends View { handleInteraction(interaction: Interaction) { switch (interaction.type) { - case 'vertical-pan-start': - this._handleVerticalPanStart(interaction); + case 'mousedown': + this._handleMouseDown(interaction); break; - case 'vertical-pan-move': - this._handleVerticalPanMove(interaction); + case 'mousemove': + this._handleMouseMove(interaction); break; - case 'vertical-pan-end': - this._handleVerticalPanEnd(interaction); + case 'mouseup': + this._handleMouseUp(interaction); break; case 'wheel-plain': this._handleWheelPlain(interaction); diff --git a/src/useCanvasInteraction.js b/src/useCanvasInteraction.js index 1cb5c37b260ff..375ec99c0c86e 100644 --- a/src/useCanvasInteraction.js +++ b/src/useCanvasInteraction.js @@ -4,50 +4,22 @@ import type {Point} from './layout'; import {useEffect} from 'react'; -export type VerticalPanStartInteraction = {| - type: 'vertical-pan-start', +export type MouseDownInteraction = {| + type: 'mousedown', payload: {| event: MouseEvent, location: Point, |}, |}; -export type VerticalPanMoveInteraction = {| - type: 'vertical-pan-move', +export type MouseMoveInteraction = {| + type: 'mousemove', payload: {| event: MouseEvent, location: Point, |}, |}; -export type VerticalPanEndInteraction = {| - type: 'vertical-pan-end', - payload: {| - event: MouseEvent, - location: Point, - |}, -|}; -export type HorizontalPanStartInteraction = {| - type: 'horizontal-pan-start', - payload: {| - event: MouseEvent, - location: Point, - |}, -|}; -export type HorizontalPanMoveInteraction = {| - type: 'horizontal-pan-move', - payload: {| - event: MouseEvent, - location: Point, - |}, -|}; -export type HorizontalPanEndInteraction = {| - type: 'horizontal-pan-end', - payload: {| - event: MouseEvent, - location: Point, - |}, -|}; -export type HoverInteraction = {| - type: 'hover', +export type MouseUpInteraction = {| + type: 'mouseup', payload: {| event: MouseEvent, location: Point, @@ -83,13 +55,9 @@ export type WheelWithMetaInteraction = {| |}; export type Interaction = - | VerticalPanStartInteraction - | VerticalPanMoveInteraction - | VerticalPanEndInteraction - | HorizontalPanStartInteraction - | HorizontalPanMoveInteraction - | HorizontalPanEndInteraction - | HoverInteraction + | MouseDownInteraction + | MouseMoveInteraction + | MouseUpInteraction | WheelPlainInteraction | WheelWithShiftInteraction | WheelWithControlInteraction @@ -137,14 +105,7 @@ export function useCanvasInteraction( const onCanvasMouseDown: MouseEventHandler = event => { interactor({ - type: 'horizontal-pan-start', - payload: { - event, - location: localToCanvasCoordinates({x: event.x, y: event.y}), - }, - }); - interactor({ - type: 'vertical-pan-start', + type: 'mousedown', payload: { event, location: localToCanvasCoordinates({x: event.x, y: event.y}), @@ -154,21 +115,7 @@ export function useCanvasInteraction( const onCanvasMouseMove: MouseEventHandler = event => { interactor({ - type: 'horizontal-pan-move', - payload: { - event, - location: localToCanvasCoordinates({x: event.x, y: event.y}), - }, - }); - interactor({ - type: 'vertical-pan-move', - payload: { - event, - location: localToCanvasCoordinates({x: event.x, y: event.y}), - }, - }); - interactor({ - type: 'hover', + type: 'mousemove', payload: { event, location: localToCanvasCoordinates({x: event.x, y: event.y}), @@ -178,14 +125,7 @@ export function useCanvasInteraction( const onDocumentMouseUp: MouseEventHandler = event => { interactor({ - type: 'horizontal-pan-end', - payload: { - event, - location: localToCanvasCoordinates({x: event.x, y: event.y}), - }, - }); - interactor({ - type: 'vertical-pan-end', + type: 'mouseup', payload: { event, location: localToCanvasCoordinates({x: event.x, y: event.y}), From 20841975ced96bfe9019e21ac3c5c865d43a20ee Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Wed, 5 Aug 2020 20:59:12 +0800 Subject: [PATCH 074/116] Listen to mouse move events when dragging offscreen (#116) --- src/useCanvasInteraction.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/useCanvasInteraction.js b/src/useCanvasInteraction.js index 375ec99c0c86e..fd85e37e4d909 100644 --- a/src/useCanvasInteraction.js +++ b/src/useCanvasInteraction.js @@ -113,7 +113,7 @@ export function useCanvasInteraction( }); }; - const onCanvasMouseMove: MouseEventHandler = event => { + const onDocumentMouseMove: MouseEventHandler = event => { interactor({ type: 'mousemove', payload: { @@ -174,18 +174,18 @@ export function useCanvasInteraction( return false; }; + document.addEventListener('mousemove', onDocumentMouseMove); document.addEventListener('mouseup', onDocumentMouseUp); - canvas.addEventListener('wheel', onCanvasWheel); canvas.addEventListener('mousedown', onCanvasMouseDown); - canvas.addEventListener('mousemove', onCanvasMouseMove); + canvas.addEventListener('wheel', onCanvasWheel); return () => { + document.removeEventListener('mousemove', onDocumentMouseMove); document.removeEventListener('mouseup', onDocumentMouseUp); - canvas.removeEventListener('wheel', onCanvasWheel); canvas.removeEventListener('mousedown', onCanvasMouseDown); - canvas.removeEventListener('mousemove', onCanvasMouseMove); + canvas.removeEventListener('wheel', onCanvasWheel); }; }, [canvasRef, interactor]); } From 020916fef6eafdfa7f9f9b2e75ad963d28772c45 Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Wed, 5 Aug 2020 21:34:28 +0800 Subject: [PATCH 075/116] Upgrade dependencies, including Speedscope fork with upstreamed fix (#118) --- package.json | 22 +- yarn.lock | 924 ++++++++++++++++++++++++++++++--------------------- 2 files changed, 549 insertions(+), 397 deletions(-) diff --git a/package.json b/package.json index 0aa2751ce6ea4..1f5b96791b83b 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "author": "Brian Vaughn ", "license": "MIT", "dependencies": { - "@elg/speedscope": "1.6.0-787837d", + "@elg/speedscope": "1.9.0-846c4e7", "array-binsearch": "^1.0.1", "clipboard-js": "^0.3.6", "d3-hierarchy": "^1.1.9", @@ -25,27 +25,27 @@ "scheduler": "^0.19.1" }, "devDependencies": { - "@babel/core": "^7.10.4", - "@testing-library/jest-dom": "^5.11.0", - "@testing-library/react": "^10.4.5", + "@babel/core": "^7.11.1", + "@testing-library/jest-dom": "^5.11.2", + "@testing-library/react": "^10.4.8", "babel-eslint": "^10.1.0", - "babel-jest": "^26.1.0", + "babel-jest": "^26.2.2", "babel-preset-react-app": "^9.1.2", "confusing-browser-globals": "^1.0.9", - "eslint": "^7.4.0", + "eslint": "^7.6.0", "eslint-config-fbjs": "^1.1.1", "eslint-config-prettier": "^6.11.0", "eslint-plugin-babel": "^5.3.1", "eslint-plugin-flowtype": "^5.2.0", - "eslint-plugin-jest": "^23.18.0", + "eslint-plugin-jest": "^23.20.0", "eslint-plugin-no-for-of-loops": "^1.0.1", "eslint-plugin-prettier": "^3.1.4", - "eslint-plugin-react": "^7.20.3", - "flow-bin": "^0.129.0", + "eslint-plugin-react": "^7.20.5", + "flow-bin": "^0.130.0", "identity-obj-proxy": "^3.0.0", - "jest": "^26.1.0", + "jest": "^26.2.2", "parcel": "2.0.0-beta.1", - "postcss-modules": "^2.0.0", + "postcss-modules": "^3.2.0", "prettier": "1.19.1" } } diff --git a/yarn.lock b/yarn.lock index dd91760f237a6..6a99e751157bb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -105,24 +105,24 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/core@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.10.4.tgz#780e8b83e496152f8dd7df63892b2e052bf1d51d" - integrity sha512-3A0tS0HWpy4XujGc7QtOIHTeNwUgWaZc/WuS5YQrfhU67jnVmsD6OGPc1AKHH0LJHQICGncy3+YUjIhVlfDdcA== +"@babel/core@^7.11.1": + version "7.11.1" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.11.1.tgz#2c55b604e73a40dc21b0e52650b11c65cf276643" + integrity sha512-XqF7F6FWQdKGGWAzGELL+aCO1p+lRY5Tj5/tbT3St1G8NaH70jhhDIKknIZaDans0OQBG5wRAldROLHSt44BgQ== dependencies: "@babel/code-frame" "^7.10.4" - "@babel/generator" "^7.10.4" - "@babel/helper-module-transforms" "^7.10.4" + "@babel/generator" "^7.11.0" + "@babel/helper-module-transforms" "^7.11.0" "@babel/helpers" "^7.10.4" - "@babel/parser" "^7.10.4" + "@babel/parser" "^7.11.1" "@babel/template" "^7.10.4" - "@babel/traverse" "^7.10.4" - "@babel/types" "^7.10.4" + "@babel/traverse" "^7.11.0" + "@babel/types" "^7.11.0" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.1" json5 "^2.1.2" - lodash "^4.17.13" + lodash "^4.17.19" resolve "^1.3.2" semver "^5.4.1" source-map "^0.5.0" @@ -157,6 +157,15 @@ lodash "^4.17.13" source-map "^0.5.0" +"@babel/generator@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.11.0.tgz#4b90c78d8c12825024568cbe83ee6c9af193585c" + integrity sha512-fEm3Uzw7Mc9Xi//qU20cBKatTfs2aOtKqmvy/Vm7RkJEGFQ4xc9myCfbXxqK//ZS8MR/ciOHw6meGASJuKmDfQ== + dependencies: + "@babel/types" "^7.11.0" + jsesc "^2.5.1" + source-map "^0.5.0" + "@babel/helper-annotate-as-pure@^7.10.1": version "7.10.1" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.1.tgz#f6d08acc6f70bbd59b436262553fb2e259a1a268" @@ -517,6 +526,19 @@ "@babel/types" "^7.10.4" lodash "^4.17.13" +"@babel/helper-module-transforms@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz#b16f250229e47211abdd84b34b64737c2ab2d359" + integrity sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg== + dependencies: + "@babel/helper-module-imports" "^7.10.4" + "@babel/helper-replace-supers" "^7.10.4" + "@babel/helper-simple-access" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.11.0" + "@babel/template" "^7.10.4" + "@babel/types" "^7.11.0" + lodash "^4.17.19" + "@babel/helper-module-transforms@^7.7.4", "@babel/helper-module-transforms@^7.7.5": version "7.7.5" resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.7.5.tgz#d044da7ffd91ec967db25cd6748f704b6b244835" @@ -687,6 +709,13 @@ dependencies: "@babel/types" "^7.10.4" +"@babel/helper-split-export-declaration@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz#f8a491244acf6a676158ac42072911ba83ad099f" + integrity sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg== + dependencies: + "@babel/types" "^7.11.0" + "@babel/helper-split-export-declaration@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz#57292af60443c4a3622cf74040ddc28e68336fd8" @@ -803,6 +832,11 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.10.4.tgz#9eedf27e1998d87739fb5028a5120557c06a1a64" integrity sha512-8jHII4hf+YVDsskTF6WuMB3X4Eh+PsUkC2ljq22so5rHvH+T8BzyL94VOdyFLNR8tBSVXOTbNHOKpR4TfRxVtA== +"@babel/parser@^7.11.0", "@babel/parser@^7.11.1": + version "7.11.1" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.1.tgz#d91a387990b21e5d20047b336bb19b0553f02ff5" + integrity sha512-u9QMIRdKVF7hfEkb3nu2LgZDIzCQPv+yHD9Eg6ruoJLjkrQ9fFz4IBSlF/9XwoNri9+2F1IY+dYuOfZrXq8t3w== + "@babel/plugin-proposal-async-generator-functions@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.4.tgz#4b65abb3d9bacc6c657aaa413e56696f9f170fc6" @@ -2480,6 +2514,21 @@ globals "^11.1.0" lodash "^4.17.13" +"@babel/traverse@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.11.0.tgz#9b996ce1b98f53f7c3e4175115605d56ed07dd24" + integrity sha512-ZB2V+LskoWKNpMq6E5UUCrjtDUh5IOTAyIl0dTjIEoXum/iKWkoIEKIRDnUucO6f+2FzNkE0oD4RLKoPIufDtg== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.11.0" + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.11.0" + "@babel/parser" "^7.11.0" + "@babel/types" "^7.11.0" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.19" + "@babel/types@^7.0.0", "@babel/types@^7.3.3", "@babel/types@^7.7.4": version "7.7.4" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.7.4.tgz#516570d539e44ddf308c07569c258ff94fde9193" @@ -2507,6 +2556,15 @@ lodash "^4.17.13" to-fast-properties "^2.0.0" +"@babel/types@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.11.0.tgz#2ae6bf1ba9ae8c3c43824e5861269871b206e90d" + integrity sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA== + dependencies: + "@babel/helper-validator-identifier" "^7.10.4" + lodash "^4.17.19" + to-fast-properties "^2.0.0" + "@bcoe/v8-coverage@^0.2.3": version "0.2.3" resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" @@ -2520,10 +2578,10 @@ exec-sh "^0.3.2" minimist "^1.2.0" -"@elg/speedscope@1.6.0-787837d": - version "1.6.0-787837d" - resolved "https://registry.yarnpkg.com/@elg/speedscope/-/speedscope-1.6.0-787837d.tgz#2b9bcd8a5d5e7eb53e3db838456eb2e745def1bf" - integrity sha512-LrPUHP9C06eLcXkKXg0PrkRIteYe75IUxJ21dBpUohWoEMMa4ET056Ycj/zj/ChxcCemHnorloH/jSS2db8M1A== +"@elg/speedscope@1.9.0-846c4e7": + version "1.9.0-846c4e7" + resolved "https://registry.yarnpkg.com/@elg/speedscope/-/speedscope-1.9.0-846c4e7.tgz#6f31b6055717f10b67dfa032c8b64bc1e6aab881" + integrity sha512-OyXdOG/kAJLbR2/UIEZDqdKpcQ1FAa/Q/vQr1Pnx+4QoqN4gM5H4eqY4MFs3VbQykjmna7SpJ6D0pldWp3641A== dependencies: opn "5.3.0" react "^16.13.1" @@ -2549,89 +2607,93 @@ resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd" integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw== -"@jest/console@^26.1.0": - version "26.1.0" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-26.1.0.tgz#f67c89e4f4d04dbcf7b052aed5ab9c74f915b954" - integrity sha512-+0lpTHMd/8pJp+Nd4lyip+/Iyf2dZJvcCqrlkeZQoQid+JlThA4M9vxHtheyrQ99jJTMQam+es4BcvZ5W5cC3A== +"@jest/console@^26.2.0": + version "26.2.0" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-26.2.0.tgz#d18f2659b90930e7ec3925fb7209f1ba2cf463f0" + integrity sha512-mXQfx3nSLwiHm1i7jbu+uvi+vvpVjNGzIQYLCfsat9rapC+MJkS4zBseNrgJE0vU921b3P67bQzhduphjY3Tig== dependencies: - "@jest/types" "^26.1.0" + "@jest/types" "^26.2.0" + "@types/node" "*" chalk "^4.0.0" - jest-message-util "^26.1.0" - jest-util "^26.1.0" + jest-message-util "^26.2.0" + jest-util "^26.2.0" slash "^3.0.0" -"@jest/core@^26.1.0": - version "26.1.0" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-26.1.0.tgz#4580555b522de412a7998b3938c851e4f9da1c18" - integrity sha512-zyizYmDJOOVke4OO/De//aiv8b07OwZzL2cfsvWF3q9YssfpcKfcnZAwDY8f+A76xXSMMYe8i/f/LPocLlByfw== - dependencies: - "@jest/console" "^26.1.0" - "@jest/reporters" "^26.1.0" - "@jest/test-result" "^26.1.0" - "@jest/transform" "^26.1.0" - "@jest/types" "^26.1.0" +"@jest/core@^26.2.2": + version "26.2.2" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-26.2.2.tgz#63de01ffce967618003dd7a0164b05c8041b81a9" + integrity sha512-UwA8gNI8aeV4FHGfGAUfO/DHjrFVvlBravF1Tm9Kt6qFE+6YHR47kFhgdepOFpADEKstyO+MVdPvkV6/dyt9sA== + dependencies: + "@jest/console" "^26.2.0" + "@jest/reporters" "^26.2.2" + "@jest/test-result" "^26.2.0" + "@jest/transform" "^26.2.2" + "@jest/types" "^26.2.0" + "@types/node" "*" ansi-escapes "^4.2.1" chalk "^4.0.0" exit "^0.1.2" graceful-fs "^4.2.4" - jest-changed-files "^26.1.0" - jest-config "^26.1.0" - jest-haste-map "^26.1.0" - jest-message-util "^26.1.0" + jest-changed-files "^26.2.0" + jest-config "^26.2.2" + jest-haste-map "^26.2.2" + jest-message-util "^26.2.0" jest-regex-util "^26.0.0" - jest-resolve "^26.1.0" - jest-resolve-dependencies "^26.1.0" - jest-runner "^26.1.0" - jest-runtime "^26.1.0" - jest-snapshot "^26.1.0" - jest-util "^26.1.0" - jest-validate "^26.1.0" - jest-watcher "^26.1.0" + jest-resolve "^26.2.2" + jest-resolve-dependencies "^26.2.2" + jest-runner "^26.2.2" + jest-runtime "^26.2.2" + jest-snapshot "^26.2.2" + jest-util "^26.2.0" + jest-validate "^26.2.0" + jest-watcher "^26.2.0" micromatch "^4.0.2" p-each-series "^2.1.0" rimraf "^3.0.0" slash "^3.0.0" strip-ansi "^6.0.0" -"@jest/environment@^26.1.0": - version "26.1.0" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-26.1.0.tgz#378853bcdd1c2443b4555ab908cfbabb851e96da" - integrity sha512-86+DNcGongbX7ai/KE/S3/NcUVZfrwvFzOOWX/W+OOTvTds7j07LtC+MgGydH5c8Ri3uIrvdmVgd1xFD5zt/xA== +"@jest/environment@^26.2.0": + version "26.2.0" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-26.2.0.tgz#f6faee1630fcc2fad208953164bccb31dbe0e45f" + integrity sha512-oCgp9NmEiJ5rbq9VI/v/yYLDpladAAVvFxZgNsnJxOETuzPZ0ZcKKHYjKYwCtPOP1WCrM5nmyuOhMStXFGHn+g== dependencies: - "@jest/fake-timers" "^26.1.0" - "@jest/types" "^26.1.0" - jest-mock "^26.1.0" + "@jest/fake-timers" "^26.2.0" + "@jest/types" "^26.2.0" + "@types/node" "*" + jest-mock "^26.2.0" -"@jest/fake-timers@^26.1.0": - version "26.1.0" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-26.1.0.tgz#9a76b7a94c351cdbc0ad53e5a748789f819a65fe" - integrity sha512-Y5F3kBVWxhau3TJ825iuWy++BAuQzK/xEa+wD9vDH3RytW9f2DbMVodfUQC54rZDX3POqdxCgcKdgcOL0rYUpA== +"@jest/fake-timers@^26.2.0": + version "26.2.0" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-26.2.0.tgz#b485c57dc4c74d61406a339807a9af4bac74b75a" + integrity sha512-45Gfe7YzYTKqTayBrEdAF0qYyAsNRBzfkV0IyVUm3cx7AsCWlnjilBM4T40w7IXT5VspOgMPikQlV0M6gHwy/g== dependencies: - "@jest/types" "^26.1.0" + "@jest/types" "^26.2.0" "@sinonjs/fake-timers" "^6.0.1" - jest-message-util "^26.1.0" - jest-mock "^26.1.0" - jest-util "^26.1.0" + "@types/node" "*" + jest-message-util "^26.2.0" + jest-mock "^26.2.0" + jest-util "^26.2.0" -"@jest/globals@^26.1.0": - version "26.1.0" - resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-26.1.0.tgz#6cc5d7cbb79b76b120f2403d7d755693cf063ab1" - integrity sha512-MKiHPNaT+ZoG85oMaYUmGHEqu98y3WO2yeIDJrs2sJqHhYOy3Z6F7F/luzFomRQ8SQ1wEkmahFAz2291Iv8EAw== +"@jest/globals@^26.2.0": + version "26.2.0" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-26.2.0.tgz#ad78f1104f250c1a4bf5184a2ba51facc59b23f6" + integrity sha512-Hoc6ScEIPaym7RNytIL2ILSUWIGKlwEv+JNFof9dGYOdvPjb2evEURSslvCMkNuNg1ECEClTE8PH7ULlMJntYA== dependencies: - "@jest/environment" "^26.1.0" - "@jest/types" "^26.1.0" - expect "^26.1.0" + "@jest/environment" "^26.2.0" + "@jest/types" "^26.2.0" + expect "^26.2.0" -"@jest/reporters@^26.1.0": - version "26.1.0" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-26.1.0.tgz#08952e90c90282e14ff49e927bdf1873617dae78" - integrity sha512-SVAysur9FOIojJbF4wLP0TybmqwDkdnFxHSPzHMMIYyBtldCW9gG+Q5xWjpMFyErDiwlRuPyMSJSU64A67Pazg== +"@jest/reporters@^26.2.2": + version "26.2.2" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-26.2.2.tgz#5a8632ab410f4fc57782bc05dcf115e91818e869" + integrity sha512-7854GPbdFTAorWVh+RNHyPO9waRIN6TcvCezKVxI1khvFq9YjINTW7J3WU+tbR038Ynn6WjYred6vtT0YmIWVQ== dependencies: "@bcoe/v8-coverage" "^0.2.3" - "@jest/console" "^26.1.0" - "@jest/test-result" "^26.1.0" - "@jest/transform" "^26.1.0" - "@jest/types" "^26.1.0" + "@jest/console" "^26.2.0" + "@jest/test-result" "^26.2.0" + "@jest/transform" "^26.2.2" + "@jest/types" "^26.2.0" chalk "^4.0.0" collect-v8-coverage "^1.0.0" exit "^0.1.2" @@ -2642,10 +2704,10 @@ istanbul-lib-report "^3.0.0" istanbul-lib-source-maps "^4.0.0" istanbul-reports "^3.0.2" - jest-haste-map "^26.1.0" - jest-resolve "^26.1.0" - jest-util "^26.1.0" - jest-worker "^26.1.0" + jest-haste-map "^26.2.2" + jest-resolve "^26.2.2" + jest-util "^26.2.0" + jest-worker "^26.2.1" slash "^3.0.0" source-map "^0.6.0" string-length "^4.0.1" @@ -2663,42 +2725,42 @@ graceful-fs "^4.2.4" source-map "^0.6.0" -"@jest/test-result@^26.1.0": - version "26.1.0" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-26.1.0.tgz#a93fa15b21ad3c7ceb21c2b4c35be2e407d8e971" - integrity sha512-Xz44mhXph93EYMA8aYDz+75mFbarTV/d/x0yMdI3tfSRs/vh4CqSxgzVmCps1fPkHDCtn0tU8IH9iCKgGeGpfw== +"@jest/test-result@^26.2.0": + version "26.2.0" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-26.2.0.tgz#51c9b165c8851cfcf7a3466019114785e154f76b" + integrity sha512-kgPlmcVafpmfyQEu36HClK+CWI6wIaAWDHNxfQtGuKsgoa2uQAYdlxjMDBEa3CvI40+2U3v36gQF6oZBkoKatw== dependencies: - "@jest/console" "^26.1.0" - "@jest/types" "^26.1.0" + "@jest/console" "^26.2.0" + "@jest/types" "^26.2.0" "@types/istanbul-lib-coverage" "^2.0.0" collect-v8-coverage "^1.0.0" -"@jest/test-sequencer@^26.1.0": - version "26.1.0" - resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-26.1.0.tgz#41a6fc8b850c3f33f48288ea9ea517c047e7f14e" - integrity sha512-Z/hcK+rTq56E6sBwMoQhSRDVjqrGtj1y14e2bIgcowARaIE1SgOanwx6gvY4Q9gTKMoZQXbXvptji+q5GYxa6Q== +"@jest/test-sequencer@^26.2.2": + version "26.2.2" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-26.2.2.tgz#5e8091f2e6c61fdf242af566cb820a4eadc6c4af" + integrity sha512-SliZWon5LNqV/lVXkeowSU6L8++FGOu3f43T01L1Gv6wnFDP00ER0utV9jyK9dVNdXqfMNCN66sfcyar/o7BNw== dependencies: - "@jest/test-result" "^26.1.0" + "@jest/test-result" "^26.2.0" graceful-fs "^4.2.4" - jest-haste-map "^26.1.0" - jest-runner "^26.1.0" - jest-runtime "^26.1.0" + jest-haste-map "^26.2.2" + jest-runner "^26.2.2" + jest-runtime "^26.2.2" -"@jest/transform@^26.1.0": - version "26.1.0" - resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-26.1.0.tgz#697f48898c2a2787c9b4cb71d09d7e617464e509" - integrity sha512-ICPm6sUXmZJieq45ix28k0s+d/z2E8CHDsq+WwtWI6kW8m7I8kPqarSEcUN86entHQ570ZBRci5OWaKL0wlAWw== +"@jest/transform@^26.2.2": + version "26.2.2" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-26.2.2.tgz#86c005c8d5d749ac54d8df53ea58675fffe7a97e" + integrity sha512-c1snhvi5wRVre1XyoO3Eef5SEWpuBCH/cEbntBUd9tI5sNYiBDmO0My/lc5IuuGYKp/HFIHV1eZpSx5yjdkhKw== dependencies: "@babel/core" "^7.1.0" - "@jest/types" "^26.1.0" + "@jest/types" "^26.2.0" babel-plugin-istanbul "^6.0.0" chalk "^4.0.0" convert-source-map "^1.4.0" fast-json-stable-stringify "^2.0.0" graceful-fs "^4.2.4" - jest-haste-map "^26.1.0" + jest-haste-map "^26.2.2" jest-regex-util "^26.0.0" - jest-util "^26.1.0" + jest-util "^26.2.0" micromatch "^4.0.2" pirates "^4.0.1" slash "^3.0.0" @@ -2715,13 +2777,14 @@ "@types/yargs" "^15.0.0" chalk "^3.0.0" -"@jest/types@^26.1.0": - version "26.1.0" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.1.0.tgz#f8afaaaeeb23b5cad49dd1f7779689941dcb6057" - integrity sha512-GXigDDsp6ZlNMhXQDeuy/iYCDsRIHJabWtDzvnn36+aqFfG14JmFV0e/iXxY4SP9vbXSiPNOWdehU5MeqrYHBQ== +"@jest/types@^26.2.0": + version "26.2.0" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.2.0.tgz#b28ca1fb517a4eb48c0addea7fcd9edc4ab45721" + integrity sha512-lvm3rJvctxd7+wxKSxxbzpDbr4FXDLaC57WEKdUIZ2cjTYuxYSc0zlyD7Z4Uqr5VdKxRUrtwIkiqBuvgf8uKJA== dependencies: "@types/istanbul-lib-coverage" "^2.0.0" "@types/istanbul-reports" "^1.1.1" + "@types/node" "*" "@types/yargs" "^15.0.0" chalk "^4.0.0" @@ -3521,30 +3584,29 @@ dom-accessibility-api "^0.4.5" pretty-format "^25.5.0" -"@testing-library/jest-dom@^5.11.0": - version "5.11.0" - resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.11.0.tgz#1439f08dc85ce7c6d3bbad0ee5d53b2206f55768" - integrity sha512-mhaCySy7dZlyfcxcYy+0jLllODHEiHkVdmwQ00wD0HrWiSx0fSVHz/0WmdlRkvhfSOuqsRsBUreXOtBvruWGQA== +"@testing-library/jest-dom@^5.11.2": + version "5.11.2" + resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.11.2.tgz#c49de331555c70127b5d7fc97344ad5265f4c54c" + integrity sha512-s+rWJx+lanEGKqvOl4qJR0rGjCrxsEjj9qjxFlg4NV4/FRD7fnUUAWPHqwpyafNHfLYArs58FADgdn4UKmjFmw== dependencies: "@babel/runtime" "^7.9.2" "@types/testing-library__jest-dom" "^5.9.1" aria-query "^4.2.2" chalk "^3.0.0" - css "^2.2.4" + css "^3.0.0" css.escape "^1.5.1" jest-diff "^25.1.0" jest-matcher-utils "^25.1.0" lodash "^4.17.15" redent "^3.0.0" -"@testing-library/react@^10.4.5": - version "10.4.5" - resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-10.4.5.tgz#e66e004d6beb60a26b4e5d4e4d9989738d7077f3" - integrity sha512-M5A0W4VphBiEm4vgnq7vHC+/e4Bp/3iIOAWap1FtIiA+Zom6BtXpY3RSTOqc8bZsCcu9gFBZ/lxaiMW6uJddWg== +"@testing-library/react@^10.4.8": + version "10.4.8" + resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-10.4.8.tgz#5eb730291b8fd81cdb2d8877770d060b044ae4a4" + integrity sha512-clgpFR6QHiRRcdhFfAKDhH8UXpNASyfkkANhtCsCVBnai+O+mK1rGtMES+Apc7ql5Wyxu7j8dcLiC4pV5VblHA== dependencies: "@babel/runtime" "^7.10.3" "@testing-library/dom" "^7.17.1" - semver "^7.3.2" "@types/aria-query@^4.2.0": version "4.2.0" @@ -3747,11 +3809,16 @@ acorn@^6.0.1, acorn@^6.0.4: resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.0.tgz#b659d2ffbafa24baf5db1cdbb2c94a983ecd2784" integrity sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw== -acorn@^7.1.1, acorn@^7.2.0: +acorn@^7.1.1: version "7.3.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.3.1.tgz#85010754db53c3fbaf3b9ea3e083aa5c5d147ffd" integrity sha512-tLc0wSnatxAQHVHUapaHdz72pi9KUyHjq5KyHjGg9Y8Ifdc79pTh2XvI6I1/chZbnM7QtNKzh66ooDogPZSleA== +acorn@^7.3.1: + version "7.4.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.0.tgz#e1ad486e6c54501634c6c397c5c121daa383607c" + integrity sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w== + aggregate-error@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.0.1.tgz#db2fe7246e536f40d9b5442a39e117d7dd6a24e0" @@ -4018,16 +4085,16 @@ babel-eslint@^10.1.0: eslint-visitor-keys "^1.0.0" resolve "^1.12.0" -babel-jest@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-26.1.0.tgz#b20751185fc7569a0f135730584044d1cb934328" - integrity sha512-Nkqgtfe7j6PxLO6TnCQQlkMm8wdTdnIF8xrdpooHCuD5hXRzVEPbPneTJKknH5Dsv3L8ip9unHDAp48YQ54Dkg== +babel-jest@^26.2.2: + version "26.2.2" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-26.2.2.tgz#70f618f2d7016ed71b232241199308985462f812" + integrity sha512-JmLuePHgA+DSOdOL8lPxCgD2LhPPm+rdw1vnxR73PpIrnmKCS2/aBhtkAcxQWuUcW2hBrH8MJ3LKXE7aWpNZyA== dependencies: - "@jest/transform" "^26.1.0" - "@jest/types" "^26.1.0" + "@jest/transform" "^26.2.2" + "@jest/types" "^26.2.0" "@types/babel__core" "^7.1.7" babel-plugin-istanbul "^6.0.0" - babel-preset-jest "^26.1.0" + babel-preset-jest "^26.2.0" chalk "^4.0.0" graceful-fs "^4.2.4" slash "^3.0.0" @@ -4057,10 +4124,10 @@ babel-plugin-istanbul@^6.0.0: istanbul-lib-instrument "^4.0.0" test-exclude "^6.0.0" -babel-plugin-jest-hoist@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.1.0.tgz#c6a774da08247a28285620a64dfadbd05dd5233a" - integrity sha512-qhqLVkkSlqmC83bdMhM8WW4Z9tB+JkjqAqlbbohS9sJLT5Ha2vfzuKqg5yenXrAjOPG2YC0WiXdH3a9PvB+YYw== +babel-plugin-jest-hoist@^26.2.0: + version "26.2.0" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.2.0.tgz#bdd0011df0d3d513e5e95f76bd53b51147aca2dd" + integrity sha512-B/hVMRv8Nh1sQ1a3EY8I0n4Y1Wty3NrR5ebOyVT302op+DOAau+xNEImGMsUWOC3++ZlMooCytKz+NgN8aKGbA== dependencies: "@babel/template" "^7.3.3" "@babel/types" "^7.3.3" @@ -4098,12 +4165,12 @@ babel-preset-current-node-syntax@^0.1.2: "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" "@babel/plugin-syntax-optional-chaining" "^7.8.3" -babel-preset-jest@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-26.1.0.tgz#612f714e5b457394acfd863793c564cbcdb7d1c1" - integrity sha512-na9qCqFksknlEj5iSdw1ehMVR06LCCTkZLGKeEtxDDdhg8xpUF09m29Kvh1pRbZ07h7AQ5ttLYUwpXL4tO6w7w== +babel-preset-jest@^26.2.0: + version "26.2.0" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-26.2.0.tgz#f198201a4e543a43eb40bc481e19736e095fd3e0" + integrity sha512-R1k8kdP3R9phYQugXeNnK/nvCGlBzG4m3EoIIukC80GXb6wCv2XiwPhK6K9MAkQcMszWBYvl2Wm+yigyXFQqXg== dependencies: - babel-plugin-jest-hoist "^26.1.0" + babel-plugin-jest-hoist "^26.2.0" babel-preset-current-node-syntax "^0.1.2" babel-preset-react-app@^9.1.2: @@ -4869,15 +4936,14 @@ css.escape@^1.5.1: resolved "https://registry.yarnpkg.com/css.escape/-/css.escape-1.5.1.tgz#42e27d4fa04ae32f931a4b4d4191fa9cddee97cb" integrity sha1-QuJ9T6BK4y+TGktNQZH6nN3ul8s= -css@^2.2.4: - version "2.2.4" - resolved "https://registry.yarnpkg.com/css/-/css-2.2.4.tgz#c646755c73971f2bba6a601e2cf2fd71b1298929" - integrity sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw== +css@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/css/-/css-3.0.0.tgz#4447a4d58fdd03367c516ca9f64ae365cee4aa5d" + integrity sha512-DG9pFfwOrzc+hawpmqX/dHYHJG+Bsdb0klhyi1sDneOgGOXy9wQIC8hzyVp1e4NRYDBdxcylvywPkkXCHAzTyQ== dependencies: - inherits "^2.0.3" + inherits "^2.0.4" source-map "^0.6.1" - source-map-resolve "^0.5.2" - urix "^0.1.0" + source-map-resolve "^0.6.0" cssesc@^0.1.0: version "0.1.0" @@ -5276,6 +5342,11 @@ elliptic@^6.0.0: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.0" +emittery@^0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.7.1.tgz#c02375a927a40948c0345cc903072597f5270451" + integrity sha512-d34LN4L6h18Bzz9xpoku2nPwKxCPlPMr3EEKTkoEBi+1/+b0lcRkRJ1UVyyZaKNeqGR3swcGl6s390DNO4YVgQ== + emoji-regex@^7.0.1: version "7.0.3" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" @@ -5450,10 +5521,10 @@ eslint-plugin-flowtype@^5.2.0: lodash "^4.17.15" string-natural-compare "^3.0.1" -eslint-plugin-jest@^23.18.0: - version "23.18.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-23.18.0.tgz#4813eacb181820ed13c5505f400956d176b25af8" - integrity sha512-wLPM/Rm1SGhxrFQ2TKM/BYsYPhn7ch6ZEK92S2o/vGkAAnDXM0I4nTIo745RIX+VlCRMFgBuJEax6XfTHMdeKg== +eslint-plugin-jest@^23.20.0: + version "23.20.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-23.20.0.tgz#e1d69c75f639e99d836642453c4e75ed22da4099" + integrity sha512-+6BGQt85OREevBDWCvhqj1yYA4+BFK4XnRZSGJionuEYmcglMZYLNNBBemwzbqUAckURaHdJSBcjHPyrtypZOw== dependencies: "@typescript-eslint/experimental-utils" "^2.5.0" @@ -5469,10 +5540,10 @@ eslint-plugin-prettier@^3.1.4: dependencies: prettier-linter-helpers "^1.0.0" -eslint-plugin-react@^7.20.3: - version "7.20.3" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.20.3.tgz#0590525e7eb83890ce71f73c2cf836284ad8c2f1" - integrity sha512-txbo090buDeyV0ugF3YMWrzLIUqpYTsWSDZV9xLSmExE1P/Kmgg9++PD931r+KEWS66O1c9R4srLVVHmeHpoAg== +eslint-plugin-react@^7.20.5: + version "7.20.5" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.20.5.tgz#29480f3071f64a04b2c3d99d9b460ce0f76fb857" + integrity sha512-ajbJfHuFnpVNJjhyrfq+pH1C0gLc2y94OiCbAXT5O0J0YCKaFEHDV8+3+mDOr+w8WguRX+vSs1bM2BDG0VLvCw== dependencies: array-includes "^3.1.1" array.prototype.flatmap "^1.2.3" @@ -5499,22 +5570,22 @@ eslint-scope@^5.0.0, eslint-scope@^5.1.0: esrecurse "^4.1.0" estraverse "^4.1.1" -eslint-utils@^2.0.0: +eslint-utils@^2.0.0, eslint-utils@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== dependencies: eslint-visitor-keys "^1.1.0" -eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.2.0: +eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== -eslint@^7.4.0: - version "7.4.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.4.0.tgz#4e35a2697e6c1972f9d6ef2b690ad319f80f206f" - integrity sha512-gU+lxhlPHu45H3JkEGgYhWhkR9wLHHEXC9FbWFnTlEkbKyZKWgWRLgf61E8zWmBuI6g5xKBph9ltg3NtZMVF8g== +eslint@^7.6.0: + version "7.6.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.6.0.tgz#522d67cfaea09724d96949c70e7a0550614d64d6" + integrity sha512-QlAManNtqr7sozWm5TF4wIH9gmUm2hE3vNRUvyoYAa4y1l5/jxD/PQStEjBMQtCqZmSep8UxrcecI60hOpe61w== dependencies: "@babel/code-frame" "^7.0.0" ajv "^6.10.0" @@ -5524,9 +5595,9 @@ eslint@^7.4.0: doctrine "^3.0.0" enquirer "^2.3.5" eslint-scope "^5.1.0" - eslint-utils "^2.0.0" - eslint-visitor-keys "^1.2.0" - espree "^7.1.0" + eslint-utils "^2.1.0" + eslint-visitor-keys "^1.3.0" + espree "^7.2.0" esquery "^1.2.0" esutils "^2.0.2" file-entry-cache "^5.0.1" @@ -5540,7 +5611,7 @@ eslint@^7.4.0: js-yaml "^3.13.1" json-stable-stringify-without-jsonify "^1.0.1" levn "^0.4.1" - lodash "^4.17.14" + lodash "^4.17.19" minimatch "^3.0.4" natural-compare "^1.4.0" optionator "^0.9.1" @@ -5553,14 +5624,14 @@ eslint@^7.4.0: text-table "^0.2.0" v8-compile-cache "^2.0.3" -espree@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/espree/-/espree-7.1.0.tgz#a9c7f18a752056735bf1ba14cb1b70adc3a5ce1c" - integrity sha512-dcorZSyfmm4WTuTnE5Y7MEN1DyoPYy1ZR783QW1FJoenn7RailyWFsq/UL6ZAAA7uXurN9FIpYyUs3OfiIW+Qw== +espree@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-7.2.0.tgz#1c263d5b513dbad0ac30c4991b93ac354e948d69" + integrity sha512-H+cQ3+3JYRMEIOl87e7QdHX70ocly5iW4+dttuR8iYSPr/hXKFb+7dBsZ7+u1adC4VrnPlTkv0+OwuPnDop19g== dependencies: - acorn "^7.2.0" + acorn "^7.3.1" acorn-jsx "^5.2.0" - eslint-visitor-keys "^1.2.0" + eslint-visitor-keys "^1.3.0" esprima@^3.1.3: version "3.1.3" @@ -5685,16 +5756,16 @@ expand-brackets@^2.1.4: snapdragon "^0.8.1" to-regex "^3.0.1" -expect@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/expect/-/expect-26.1.0.tgz#8c62e31d0f8d5a8ebb186ee81473d15dd2fbf7c8" - integrity sha512-QbH4LZXDsno9AACrN9eM0zfnby9G+OsdNgZUohjg/P0mLy1O+/bzTAJGT6VSIjVCe8yKM6SzEl/ckEOFBT7Vnw== +expect@^26.2.0: + version "26.2.0" + resolved "https://registry.yarnpkg.com/expect/-/expect-26.2.0.tgz#0140dd9cc7376d7833852e9cda88c05414f1efba" + integrity sha512-8AMBQ9UVcoUXt0B7v+5/U5H6yiUR87L6eKCfjE3spx7Ya5lF+ebUo37MCFBML2OiLfkX1sxmQOZhIDonyVTkcw== dependencies: - "@jest/types" "^26.1.0" + "@jest/types" "^26.2.0" ansi-styles "^4.0.0" jest-get-type "^26.0.0" - jest-matcher-utils "^26.1.0" - jest-message-util "^26.1.0" + jest-matcher-utils "^26.2.0" + jest-message-util "^26.2.0" jest-regex-util "^26.0.0" extend-shallow@^2.0.1: @@ -5888,10 +5959,10 @@ flatted@^2.0.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== -flow-bin@^0.129.0: - version "0.129.0" - resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.129.0.tgz#50294d6e335dd97d095c27b096ea0b94c2415d55" - integrity sha512-WLXOj09oCK6nODVKM5uxvAzBpxXeI304E60tELMeQd/TJsyfbykNCZ+e4xml9eUOyoac9nDL3YrJpPZMzq0tMA== +flow-bin@^0.130.0: + version "0.130.0" + resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.130.0.tgz#e25eaf891af96da371ff6a9fa99d709f24ce9252" + integrity sha512-1TSLwCPXvKPwiae7Fh+dpipCzwlHQ1UcBHfCpQImz+hsxYIUWkLWJWEm34bY6I7dSM4ekSiVeP02BhzVJGwtpw== follow-redirects@^1.0.0: version "1.9.0" @@ -6305,6 +6376,13 @@ icss-replace-symbols@1.1.0, icss-replace-symbols@^1.1.0: resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded" integrity sha1-Bupvg2ead0njhs/h/oEq5dsiPe0= +icss-utils@^4.0.0, icss-utils@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-4.1.1.tgz#21170b53789ee27447c2f47dd683081403f9a467" + integrity sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA== + dependencies: + postcss "^7.0.14" + identity-obj-proxy@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz#94d2bda96084453ef36fbc5aaec37e0f79f1fc14" @@ -6775,57 +6853,57 @@ istanbul-reports@^3.0.2: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" -jest-changed-files@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-26.1.0.tgz#de66b0f30453bca2aff98e9400f75905da495305" - integrity sha512-HS5MIJp3B8t0NRKGMCZkcDUZo36mVRvrDETl81aqljT1S9tqiHRSpyoOvWg9ZilzZG9TDisDNaN1IXm54fLRZw== +jest-changed-files@^26.2.0: + version "26.2.0" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-26.2.0.tgz#b4946201defe0c919a2f3d601e9f98cb21dacc15" + integrity sha512-+RyJb+F1K/XBLIYiL449vo5D+CvlHv29QveJUWNPXuUicyZcq+tf1wNxmmFeRvAU1+TzhwqczSjxnCCFt7+8iA== dependencies: - "@jest/types" "^26.1.0" + "@jest/types" "^26.2.0" execa "^4.0.0" throat "^5.0.0" -jest-cli@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-26.1.0.tgz#eb9ec8a18cf3b6aa556d9deaa9e24be12b43ad87" - integrity sha512-Imumvjgi3rU7stq6SJ1JUEMaV5aAgJYXIs0jPqdUnF47N/Tk83EXfmtvNKQ+SnFVI6t6mDOvfM3aA9Sg6kQPSw== +jest-cli@^26.2.2: + version "26.2.2" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-26.2.2.tgz#4c273e5474baafac1eb15fd25aaafb4703f5ffbc" + integrity sha512-vVcly0n/ijZvdy6gPQiQt0YANwX2hLTPQZHtW7Vi3gcFdKTtif7YpI85F8R8JYy5DFSWz4x1OW0arnxlziu5Lw== dependencies: - "@jest/core" "^26.1.0" - "@jest/test-result" "^26.1.0" - "@jest/types" "^26.1.0" + "@jest/core" "^26.2.2" + "@jest/test-result" "^26.2.0" + "@jest/types" "^26.2.0" chalk "^4.0.0" exit "^0.1.2" graceful-fs "^4.2.4" import-local "^3.0.2" is-ci "^2.0.0" - jest-config "^26.1.0" - jest-util "^26.1.0" - jest-validate "^26.1.0" + jest-config "^26.2.2" + jest-util "^26.2.0" + jest-validate "^26.2.0" prompts "^2.0.1" yargs "^15.3.1" -jest-config@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-26.1.0.tgz#9074f7539acc185e0113ad6d22ed589c16a37a73" - integrity sha512-ONTGeoMbAwGCdq4WuKkMcdMoyfs5CLzHEkzFOlVvcDXufZSaIWh/OXMLa2fwKXiOaFcqEw8qFr4VOKJQfn4CVw== +jest-config@^26.2.2: + version "26.2.2" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-26.2.2.tgz#f3ebc7e2bc3f49de8ed3f8007152f345bb111917" + integrity sha512-2lhxH0y4YFOijMJ65usuf78m7+9/8+hAb1PZQtdRdgnQpAb4zP6KcVDDktpHEkspBKnc2lmFu+RQdHukUUbiTg== dependencies: "@babel/core" "^7.1.0" - "@jest/test-sequencer" "^26.1.0" - "@jest/types" "^26.1.0" - babel-jest "^26.1.0" + "@jest/test-sequencer" "^26.2.2" + "@jest/types" "^26.2.0" + babel-jest "^26.2.2" chalk "^4.0.0" deepmerge "^4.2.2" glob "^7.1.1" graceful-fs "^4.2.4" - jest-environment-jsdom "^26.1.0" - jest-environment-node "^26.1.0" + jest-environment-jsdom "^26.2.0" + jest-environment-node "^26.2.0" jest-get-type "^26.0.0" - jest-jasmine2 "^26.1.0" + jest-jasmine2 "^26.2.2" jest-regex-util "^26.0.0" - jest-resolve "^26.1.0" - jest-util "^26.1.0" - jest-validate "^26.1.0" + jest-resolve "^26.2.2" + jest-util "^26.2.0" + jest-validate "^26.2.0" micromatch "^4.0.2" - pretty-format "^26.1.0" + pretty-format "^26.2.0" jest-diff@^25.1.0, jest-diff@^25.2.1, jest-diff@^25.5.0: version "25.5.0" @@ -6837,15 +6915,15 @@ jest-diff@^25.1.0, jest-diff@^25.2.1, jest-diff@^25.5.0: jest-get-type "^25.2.6" pretty-format "^25.5.0" -jest-diff@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-26.1.0.tgz#00a549bdc936c9691eb4dc25d1fbd78bf456abb2" - integrity sha512-GZpIcom339y0OXznsEKjtkfKxNdg7bVbEofK8Q6MnevTIiR1jNhDWKhRX6X0SDXJlwn3dy59nZ1z55fLkAqPWg== +jest-diff@^26.2.0: + version "26.2.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-26.2.0.tgz#dee62c771adbb23ae585f3f1bd289a6e8ef4f298" + integrity sha512-Wu4Aopi2nzCsHWLBlD48TgRy3Z7OsxlwvHNd1YSnHc7q1NJfrmyCPoUXrTIrydQOG5ApaYpsAsdfnMbJqV1/wQ== dependencies: chalk "^4.0.0" diff-sequences "^26.0.0" jest-get-type "^26.0.0" - pretty-format "^26.1.0" + pretty-format "^26.2.0" jest-docblock@^26.0.0: version "26.0.0" @@ -6854,39 +6932,41 @@ jest-docblock@^26.0.0: dependencies: detect-newline "^3.0.0" -jest-each@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-26.1.0.tgz#e35449875009a22d74d1bda183b306db20f286f7" - integrity sha512-lYiSo4Igr81q6QRsVQq9LIkJW0hZcKxkIkHzNeTMPENYYDw/W/Raq28iJ0sLlNFYz2qxxeLnc5K2gQoFYlu2bA== +jest-each@^26.2.0: + version "26.2.0" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-26.2.0.tgz#aec8efa01d072d7982c900e74940863385fa884e" + integrity sha512-gHPCaho1twWHB5bpcfnozlc6mrMi+VAewVPNgmwf81x2Gzr6XO4dl+eOrwPWxbkYlgjgrYjWK2xgKnixbzH3Ew== dependencies: - "@jest/types" "^26.1.0" + "@jest/types" "^26.2.0" chalk "^4.0.0" jest-get-type "^26.0.0" - jest-util "^26.1.0" - pretty-format "^26.1.0" + jest-util "^26.2.0" + pretty-format "^26.2.0" -jest-environment-jsdom@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-26.1.0.tgz#9dc7313ffe1b59761dad1fedb76e2503e5d37c5b" - integrity sha512-dWfiJ+spunVAwzXbdVqPH1LbuJW/kDL+FyqgA5YzquisHqTi0g9hquKif9xKm7c1bKBj6wbmJuDkeMCnxZEpUw== - dependencies: - "@jest/environment" "^26.1.0" - "@jest/fake-timers" "^26.1.0" - "@jest/types" "^26.1.0" - jest-mock "^26.1.0" - jest-util "^26.1.0" +jest-environment-jsdom@^26.2.0: + version "26.2.0" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-26.2.0.tgz#6443a6f3569297dcaa4371dddf93acaf167302dc" + integrity sha512-sDG24+5M4NuIGzkI3rJW8XUlrpkvIdE9Zz4jhD8OBnVxAw+Y1jUk9X+lAOD48nlfUTlnt3lbAI3k2Ox+WF3S0g== + dependencies: + "@jest/environment" "^26.2.0" + "@jest/fake-timers" "^26.2.0" + "@jest/types" "^26.2.0" + "@types/node" "*" + jest-mock "^26.2.0" + jest-util "^26.2.0" jsdom "^16.2.2" -jest-environment-node@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-26.1.0.tgz#8bb387b3eefb132eab7826f9a808e4e05618960b" - integrity sha512-DNm5x1aQH0iRAe9UYAkZenuzuJ69VKzDCAYISFHQ5i9e+2Tbeu2ONGY7YStubCLH8a1wdKBgqScYw85+ySxqxg== +jest-environment-node@^26.2.0: + version "26.2.0" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-26.2.0.tgz#fee89e06bdd4bed3f75ee2978d73ede9bb57a681" + integrity sha512-4M5ExTYkJ19efBzkiXtBi74JqKLDciEk4CEsp5tTjWGYMrlKFQFtwIVG3tW1OGE0AlXhZjuHPwubuRYY4j4uOw== dependencies: - "@jest/environment" "^26.1.0" - "@jest/fake-timers" "^26.1.0" - "@jest/types" "^26.1.0" - jest-mock "^26.1.0" - jest-util "^26.1.0" + "@jest/environment" "^26.2.0" + "@jest/fake-timers" "^26.2.0" + "@jest/types" "^26.2.0" + "@types/node" "*" + jest-mock "^26.2.0" + jest-util "^26.2.0" jest-get-type@^25.2.6: version "25.2.6" @@ -6898,56 +6978,58 @@ jest-get-type@^26.0.0: resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-26.0.0.tgz#381e986a718998dbfafcd5ec05934be538db4039" integrity sha512-zRc1OAPnnws1EVfykXOj19zo2EMw5Hi6HLbFCSjpuJiXtOWAYIjNsHVSbpQ8bDX7L5BGYGI8m+HmKdjHYFF0kg== -jest-haste-map@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-26.1.0.tgz#ef31209be73f09b0d9445e7d213e1b53d0d1476a" - integrity sha512-WeBS54xCIz9twzkEdm6+vJBXgRBQfdbbXD0dk8lJh7gLihopABlJmIQFdWSDDtuDe4PRiObsjZSUjbJ1uhWEpA== +jest-haste-map@^26.2.2: + version "26.2.2" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-26.2.2.tgz#6d4267b1903854bfdf6a871419f35a82f03ae71e" + integrity sha512-3sJlMSt+NHnzCB+0KhJ1Ut4zKJBiJOlbrqEYNdRQGlXTv8kqzZWjUKQRY3pkjmlf+7rYjAV++MQ4D6g4DhAyOg== dependencies: - "@jest/types" "^26.1.0" + "@jest/types" "^26.2.0" "@types/graceful-fs" "^4.1.2" + "@types/node" "*" anymatch "^3.0.3" fb-watchman "^2.0.0" graceful-fs "^4.2.4" - jest-serializer "^26.1.0" - jest-util "^26.1.0" - jest-worker "^26.1.0" + jest-regex-util "^26.0.0" + jest-serializer "^26.2.0" + jest-util "^26.2.0" + jest-worker "^26.2.1" micromatch "^4.0.2" sane "^4.0.3" walker "^1.0.7" - which "^2.0.2" optionalDependencies: fsevents "^2.1.2" -jest-jasmine2@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-26.1.0.tgz#4dfe349b2b2d3c6b3a27c024fd4cb57ac0ed4b6f" - integrity sha512-1IPtoDKOAG+MeBrKvvuxxGPJb35MTTRSDglNdWWCndCB3TIVzbLThRBkwH9P081vXLgiJHZY8Bz3yzFS803xqQ== +jest-jasmine2@^26.2.2: + version "26.2.2" + resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-26.2.2.tgz#d82b1721fac2b153a4f8b3f0c95e81e702812de2" + integrity sha512-Q8AAHpbiZMVMy4Hz9j1j1bg2yUmPa1W9StBvcHqRaKa9PHaDUMwds8LwaDyzP/2fkybcTQE4+pTMDOG9826tEw== dependencies: "@babel/traverse" "^7.1.0" - "@jest/environment" "^26.1.0" + "@jest/environment" "^26.2.0" "@jest/source-map" "^26.1.0" - "@jest/test-result" "^26.1.0" - "@jest/types" "^26.1.0" + "@jest/test-result" "^26.2.0" + "@jest/types" "^26.2.0" + "@types/node" "*" chalk "^4.0.0" co "^4.6.0" - expect "^26.1.0" + expect "^26.2.0" is-generator-fn "^2.0.0" - jest-each "^26.1.0" - jest-matcher-utils "^26.1.0" - jest-message-util "^26.1.0" - jest-runtime "^26.1.0" - jest-snapshot "^26.1.0" - jest-util "^26.1.0" - pretty-format "^26.1.0" + jest-each "^26.2.0" + jest-matcher-utils "^26.2.0" + jest-message-util "^26.2.0" + jest-runtime "^26.2.2" + jest-snapshot "^26.2.2" + jest-util "^26.2.0" + pretty-format "^26.2.0" throat "^5.0.0" -jest-leak-detector@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-26.1.0.tgz#039c3a07ebcd8adfa984b6ac015752c35792e0a6" - integrity sha512-dsMnKF+4BVOZwvQDlgn3MG+Ns4JuLv8jNvXH56bgqrrboyCbI1rQg6EI5rs+8IYagVcfVP2yZFKfWNZy0rK0Hw== +jest-leak-detector@^26.2.0: + version "26.2.0" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-26.2.0.tgz#073ee6d8db7a9af043e7ce99d8eea17a4fb0cc50" + integrity sha512-aQdzTX1YiufkXA1teXZu5xXOJgy7wZQw6OJ0iH5CtQlOETe6gTSocaYKUNui1SzQ91xmqEUZ/WRavg9FD82rtQ== dependencies: jest-get-type "^26.0.0" - pretty-format "^26.1.0" + pretty-format "^26.2.0" jest-matcher-utils@^25.1.0: version "25.5.0" @@ -6959,23 +7041,23 @@ jest-matcher-utils@^25.1.0: jest-get-type "^25.2.6" pretty-format "^25.5.0" -jest-matcher-utils@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-26.1.0.tgz#cf75a41bd413dda784f022de5a65a2a5c73a5c92" - integrity sha512-PW9JtItbYvES/xLn5mYxjMd+Rk+/kIt88EfH3N7w9KeOrHWaHrdYPnVHndGbsFGRJ2d5gKtwggCvkqbFDoouQA== +jest-matcher-utils@^26.2.0: + version "26.2.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-26.2.0.tgz#b107af98c2b8c557ffd46c1adf06f794aa52d622" + integrity sha512-2cf/LW2VFb3ayPHrH36ZDjp9+CAeAe/pWBAwsV8t3dKcrINzXPVxq8qMWOxwt5BaeBCx4ZupVGH7VIgB8v66vQ== dependencies: chalk "^4.0.0" - jest-diff "^26.1.0" + jest-diff "^26.2.0" jest-get-type "^26.0.0" - pretty-format "^26.1.0" + pretty-format "^26.2.0" -jest-message-util@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-26.1.0.tgz#52573fbb8f5cea443c4d1747804d7a238a3e233c" - integrity sha512-dY0+UlldiAJwNDJ08SF0HdF32g9PkbF2NRK/+2iMPU40O6q+iSn1lgog/u0UH8ksWoPv0+gNq8cjhYO2MFtT0g== +jest-message-util@^26.2.0: + version "26.2.0" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-26.2.0.tgz#757fbc1323992297092bb9016a71a2eb12fd22ea" + integrity sha512-g362RhZaJuqeqG108n1sthz5vNpzTNy926eNDszo4ncRbmmcMRIUAZibnd6s5v2XSBCChAxQtCoN25gnzp7JbQ== dependencies: "@babel/code-frame" "^7.0.0" - "@jest/types" "^26.1.0" + "@jest/types" "^26.2.0" "@types/stack-utils" "^1.0.1" chalk "^4.0.0" graceful-fs "^4.2.4" @@ -6983,182 +7065,188 @@ jest-message-util@^26.1.0: slash "^3.0.0" stack-utils "^2.0.2" -jest-mock@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-26.1.0.tgz#80d8286da1f05a345fbad1bfd6fa49a899465d3d" - integrity sha512-1Rm8EIJ3ZFA8yCIie92UbxZWj9SuVmUGcyhLHyAhY6WI3NIct38nVcfOPWhJteqSn8V8e3xOMha9Ojfazfpovw== +jest-mock@^26.2.0: + version "26.2.0" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-26.2.0.tgz#a1b3303ab38c34aa1dbbc16ab57cdc1a59ed50d1" + integrity sha512-XeC7yWtWmWByoyVOHSsE7NYsbXJLtJNgmhD7z4MKumKm6ET0si81bsSLbQ64L5saK3TgsHo2B/UqG5KNZ1Sp/Q== dependencies: - "@jest/types" "^26.1.0" + "@jest/types" "^26.2.0" + "@types/node" "*" -jest-pnp-resolver@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.1.tgz#ecdae604c077a7fbc70defb6d517c3c1c898923a" - integrity sha512-pgFw2tm54fzgYvc/OHrnysABEObZCUNFnhjoRjaVOCN8NYc032/gVjPaHD4Aq6ApkSieWtfKAFQtmDKAmhupnQ== +jest-pnp-resolver@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz#b704ac0ae028a89108a4d040b3f919dfddc8e33c" + integrity sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w== jest-regex-util@^26.0.0: version "26.0.0" resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-26.0.0.tgz#d25e7184b36e39fd466c3bc41be0971e821fee28" integrity sha512-Gv3ZIs/nA48/Zvjrl34bf+oD76JHiGDUxNOVgUjh3j890sblXryjY4rss71fPtD/njchl6PSE2hIhvyWa1eT0A== -jest-resolve-dependencies@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-26.1.0.tgz#1ce36472f864a5dadf7dc82fa158e1c77955691b" - integrity sha512-fQVEPHHQ1JjHRDxzlLU/buuQ9om+hqW6Vo928aa4b4yvq4ZHBtRSDsLdKQLuCqn5CkTVpYZ7ARh2fbA8WkRE6g== +jest-resolve-dependencies@^26.2.2: + version "26.2.2" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-26.2.2.tgz#2ad3cd9281730e9a5c487cd846984c5324e47929" + integrity sha512-S5vufDmVbQXnpP7435gr710xeBGUFcKNpNswke7RmFvDQtmqPjPVU/rCeMlEU0p6vfpnjhwMYeaVjKZAy5QYJA== dependencies: - "@jest/types" "^26.1.0" + "@jest/types" "^26.2.0" jest-regex-util "^26.0.0" - jest-snapshot "^26.1.0" + jest-snapshot "^26.2.2" -jest-resolve@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-26.1.0.tgz#a530eaa302b1f6fa0479079d1561dd69abc00e68" - integrity sha512-KsY1JV9FeVgEmwIISbZZN83RNGJ1CC+XUCikf/ZWJBX/tO4a4NvA21YixokhdR9UnmPKKAC4LafVixJBrwlmfg== +jest-resolve@^26.2.2: + version "26.2.2" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-26.2.2.tgz#324a20a516148d61bffa0058ed0c77c510ecfd3e" + integrity sha512-ye9Tj/ILn/0OgFPE/3dGpQPUqt4dHwIocxt5qSBkyzxQD8PbL0bVxBogX2FHxsd3zJA7V2H/cHXnBnNyyT9YoQ== dependencies: - "@jest/types" "^26.1.0" + "@jest/types" "^26.2.0" chalk "^4.0.0" graceful-fs "^4.2.4" - jest-pnp-resolver "^1.2.1" - jest-util "^26.1.0" + jest-pnp-resolver "^1.2.2" + jest-util "^26.2.0" read-pkg-up "^7.0.1" resolve "^1.17.0" slash "^3.0.0" -jest-runner@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-26.1.0.tgz#457f7fc522afe46ca6db1dccf19f87f500b3288d" - integrity sha512-elvP7y0fVDREnfqit0zAxiXkDRSw6dgCkzPCf1XvIMnSDZ8yogmSKJf192dpOgnUVykmQXwYYJnCx641uLTgcw== +jest-runner@^26.2.2: + version "26.2.2" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-26.2.2.tgz#6d03d057886e9c782e10b2cf37443f902fe0e39e" + integrity sha512-/qb6ptgX+KQ+aNMohJf1We695kaAfuu3u3ouh66TWfhTpLd9WbqcF6163d/tMoEY8GqPztXPLuyG0rHRVDLxCA== dependencies: - "@jest/console" "^26.1.0" - "@jest/environment" "^26.1.0" - "@jest/test-result" "^26.1.0" - "@jest/types" "^26.1.0" + "@jest/console" "^26.2.0" + "@jest/environment" "^26.2.0" + "@jest/test-result" "^26.2.0" + "@jest/types" "^26.2.0" + "@types/node" "*" chalk "^4.0.0" + emittery "^0.7.1" exit "^0.1.2" graceful-fs "^4.2.4" - jest-config "^26.1.0" + jest-config "^26.2.2" jest-docblock "^26.0.0" - jest-haste-map "^26.1.0" - jest-jasmine2 "^26.1.0" - jest-leak-detector "^26.1.0" - jest-message-util "^26.1.0" - jest-resolve "^26.1.0" - jest-runtime "^26.1.0" - jest-util "^26.1.0" - jest-worker "^26.1.0" + jest-haste-map "^26.2.2" + jest-leak-detector "^26.2.0" + jest-message-util "^26.2.0" + jest-resolve "^26.2.2" + jest-runtime "^26.2.2" + jest-util "^26.2.0" + jest-worker "^26.2.1" source-map-support "^0.5.6" throat "^5.0.0" -jest-runtime@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-26.1.0.tgz#45a37af42115f123ed5c51f126c05502da2469cb" - integrity sha512-1qiYN+EZLmG1QV2wdEBRf+Ci8i3VSfIYLF02U18PiUDrMbhfpN/EAMMkJtT02jgJUoaEOpHAIXG6zS3QRMzRmA== +jest-runtime@^26.2.2: + version "26.2.2" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-26.2.2.tgz#2480ff79320680a643031dd21998d7c63d83ab68" + integrity sha512-a8VXM3DxCDnCIdl9+QucWFfQ28KdqmyVFqeKLigHdErtsx56O2ZIdQkhFSuP1XtVrG9nTNHbKxjh5XL1UaFDVQ== dependencies: - "@jest/console" "^26.1.0" - "@jest/environment" "^26.1.0" - "@jest/fake-timers" "^26.1.0" - "@jest/globals" "^26.1.0" + "@jest/console" "^26.2.0" + "@jest/environment" "^26.2.0" + "@jest/fake-timers" "^26.2.0" + "@jest/globals" "^26.2.0" "@jest/source-map" "^26.1.0" - "@jest/test-result" "^26.1.0" - "@jest/transform" "^26.1.0" - "@jest/types" "^26.1.0" + "@jest/test-result" "^26.2.0" + "@jest/transform" "^26.2.2" + "@jest/types" "^26.2.0" "@types/yargs" "^15.0.0" chalk "^4.0.0" collect-v8-coverage "^1.0.0" exit "^0.1.2" glob "^7.1.3" graceful-fs "^4.2.4" - jest-config "^26.1.0" - jest-haste-map "^26.1.0" - jest-message-util "^26.1.0" - jest-mock "^26.1.0" + jest-config "^26.2.2" + jest-haste-map "^26.2.2" + jest-message-util "^26.2.0" + jest-mock "^26.2.0" jest-regex-util "^26.0.0" - jest-resolve "^26.1.0" - jest-snapshot "^26.1.0" - jest-util "^26.1.0" - jest-validate "^26.1.0" + jest-resolve "^26.2.2" + jest-snapshot "^26.2.2" + jest-util "^26.2.0" + jest-validate "^26.2.0" slash "^3.0.0" strip-bom "^4.0.0" yargs "^15.3.1" -jest-serializer@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-26.1.0.tgz#72a394531fc9b08e173dc7d297440ac610d95022" - integrity sha512-eqZOQG/0+MHmr25b2Z86g7+Kzd5dG9dhCiUoyUNJPgiqi38DqbDEOlHcNijyfZoj74soGBohKBZuJFS18YTJ5w== +jest-serializer@^26.2.0: + version "26.2.0" + resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-26.2.0.tgz#92dcae5666322410f4bf50211dd749274959ddac" + integrity sha512-V7snZI9IVmyJEu0Qy0inmuXgnMWDtrsbV2p9CRAcmlmPVwpC2ZM8wXyYpiugDQnwLHx0V4+Pnog9Exb3UO8M6Q== dependencies: + "@types/node" "*" graceful-fs "^4.2.4" -jest-snapshot@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-26.1.0.tgz#c36ed1e0334bd7bd2fe5ad07e93a364ead7e1349" - integrity sha512-YhSbU7eMTVQO/iRbNs8j0mKRxGp4plo7sJ3GzOQ0IYjvsBiwg0T1o0zGQAYepza7lYHuPTrG5J2yDd0CE2YxSw== +jest-snapshot@^26.2.2: + version "26.2.2" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-26.2.2.tgz#9d2eda083a4a1017b157e351868749bd63211799" + integrity sha512-NdjD8aJS7ePu268Wy/n/aR1TUisG0BOY+QOW4f6h46UHEKOgYmmkvJhh2BqdVZQ0BHSxTMt04WpCf9njzx8KtA== dependencies: "@babel/types" "^7.0.0" - "@jest/types" "^26.1.0" + "@jest/types" "^26.2.0" "@types/prettier" "^2.0.0" chalk "^4.0.0" - expect "^26.1.0" + expect "^26.2.0" graceful-fs "^4.2.4" - jest-diff "^26.1.0" + jest-diff "^26.2.0" jest-get-type "^26.0.0" - jest-haste-map "^26.1.0" - jest-matcher-utils "^26.1.0" - jest-message-util "^26.1.0" - jest-resolve "^26.1.0" + jest-haste-map "^26.2.2" + jest-matcher-utils "^26.2.0" + jest-message-util "^26.2.0" + jest-resolve "^26.2.2" natural-compare "^1.4.0" - pretty-format "^26.1.0" + pretty-format "^26.2.0" semver "^7.3.2" -jest-util@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-26.1.0.tgz#80e85d4ba820decacf41a691c2042d5276e5d8d8" - integrity sha512-rNMOwFQevljfNGvbzNQAxdmXQ+NawW/J72dmddsK0E8vgxXCMtwQ/EH0BiWEIxh0hhMcTsxwAxINt7Lh46Uzbg== +jest-util@^26.2.0: + version "26.2.0" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-26.2.0.tgz#0597d2a27c559340957609f106c408c17c1d88ac" + integrity sha512-YmDwJxLZ1kFxpxPfhSJ0rIkiZOM0PQbRcfH0TzJOhqCisCAsI1WcmoQqO83My9xeVA2k4n+rzg2UuexVKzPpig== dependencies: - "@jest/types" "^26.1.0" + "@jest/types" "^26.2.0" + "@types/node" "*" chalk "^4.0.0" graceful-fs "^4.2.4" is-ci "^2.0.0" micromatch "^4.0.2" -jest-validate@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-26.1.0.tgz#942c85ad3d60f78250c488a7f85d8f11a29788e7" - integrity sha512-WPApOOnXsiwhZtmkDsxnpye+XLb/tUISP+H6cHjfUIXvlG+eKwP+isnivsxlHCPaO9Q5wvbhloIBkdF3qUn+Nw== +jest-validate@^26.2.0: + version "26.2.0" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-26.2.0.tgz#97fedf3e7984b7608854cbf925b9ca6ebcbdb78a" + integrity sha512-8XKn3hM6VIVmLNuyzYLCPsRCT83o8jMZYhbieh4dAyKLc4Ypr36rVKC+c8WMpWkfHHpGnEkvWUjjIAyobEIY/Q== dependencies: - "@jest/types" "^26.1.0" + "@jest/types" "^26.2.0" camelcase "^6.0.0" chalk "^4.0.0" jest-get-type "^26.0.0" leven "^3.1.0" - pretty-format "^26.1.0" + pretty-format "^26.2.0" -jest-watcher@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-26.1.0.tgz#99812a0cd931f0cb3d153180426135ab83e4d8f2" - integrity sha512-ffEOhJl2EvAIki613oPsSG11usqnGUzIiK7MMX6hE4422aXOcVEG3ySCTDFLn1+LZNXGPE8tuJxhp8OBJ1pgzQ== +jest-watcher@^26.2.0: + version "26.2.0" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-26.2.0.tgz#45bdf2fecadd19c0a501f3b071a474dca636825b" + integrity sha512-674Boco4Joe0CzgKPL6K4Z9LgyLx+ZvW2GilbpYb8rFEUkmDGgsZdv1Hv5rxsRpb1HLgKUOL/JfbttRCuFdZXQ== dependencies: - "@jest/test-result" "^26.1.0" - "@jest/types" "^26.1.0" + "@jest/test-result" "^26.2.0" + "@jest/types" "^26.2.0" + "@types/node" "*" ansi-escapes "^4.2.1" chalk "^4.0.0" - jest-util "^26.1.0" + jest-util "^26.2.0" string-length "^4.0.1" -jest-worker@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.1.0.tgz#65d5641af74e08ccd561c240e7db61284f82f33d" - integrity sha512-Z9P5pZ6UC+kakMbNJn+tA2RdVdNX5WH1x+5UCBZ9MxIK24pjYtFt96fK+UwBTrjLYm232g1xz0L3eTh51OW+yQ== +jest-worker@^26.2.1: + version "26.2.1" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.2.1.tgz#5d630ab93f666b53f911615bc13e662b382bd513" + integrity sha512-+XcGMMJDTeEGncRb5M5Zq9P7K4sQ1sirhjdOxsN1462h6lFo9w59bl2LVQmdGEEeU3m+maZCkS2Tcc9SfCHO4A== dependencies: + "@types/node" "*" merge-stream "^2.0.0" supports-color "^7.0.0" -jest@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest/-/jest-26.1.0.tgz#2f3aa7bcffb9bfd025473f83bbbf46a3af026263" - integrity sha512-LIti8jppw5BcQvmNJe4w2g1N/3V68HUfAv9zDVm7v+VAtQulGhH0LnmmiVkbNE4M4I43Bj2fXPiBGKt26k9tHw== +jest@^26.2.2: + version "26.2.2" + resolved "https://registry.yarnpkg.com/jest/-/jest-26.2.2.tgz#a022303887b145147204c5f66e6a5c832333c7e7" + integrity sha512-EkJNyHiAG1+A8pqSz7cXttoVa34hOEzN/MrnJhYnfp5VHxflVcf2pu3oJSrhiy6LfIutLdWo+n6q63tjcoIeig== dependencies: - "@jest/core" "^26.1.0" + "@jest/core" "^26.2.2" import-local "^3.0.2" - jest-cli "^26.1.0" + jest-cli "^26.2.2" js-levenshtein@^1.1.3, js-levenshtein@^1.1.6: version "1.1.6" @@ -7490,6 +7578,11 @@ lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== +lodash@^4.17.19: + version "4.17.19" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b" + integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ== + log-symbols@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-3.0.0.tgz#f3a08516a5dea893336a7dee14d18a1cfdab77c4" @@ -8418,6 +8511,13 @@ postcss-modules-extract-imports@1.1.0: dependencies: postcss "^6.0.1" +postcss-modules-extract-imports@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz#818719a1ae1da325f9832446b01136eeb493cd7e" + integrity sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ== + dependencies: + postcss "^7.0.5" + postcss-modules-local-by-default@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz#f7d80c398c5a393fa7964466bd19500a7d61c069" @@ -8426,6 +8526,16 @@ postcss-modules-local-by-default@1.2.0: css-selector-tokenizer "^0.7.0" postcss "^6.0.1" +postcss-modules-local-by-default@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz#bb14e0cc78279d504dbdcbfd7e0ca28993ffbbb0" + integrity sha512-e3xDq+LotiGesympRlKNgaJ0PCzoUIdpH0dj47iWAui/kyTgh3CiAr1qP54uodmJhl6p9rN6BoNcdEDVJx9RDw== + dependencies: + icss-utils "^4.1.1" + postcss "^7.0.32" + postcss-selector-parser "^6.0.2" + postcss-value-parser "^4.1.0" + postcss-modules-scope@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz#d6ea64994c79f97b62a72b426fbe6056a194bb90" @@ -8434,6 +8544,14 @@ postcss-modules-scope@1.1.0: css-selector-tokenizer "^0.7.0" postcss "^6.0.1" +postcss-modules-scope@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz#385cae013cc7743f5a7d7602d1073a89eaae62ee" + integrity sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ== + dependencies: + postcss "^7.0.6" + postcss-selector-parser "^6.0.0" + postcss-modules-values@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz#ecffa9d7e192518389f42ad0e83f72aec456ea20" @@ -8442,15 +8560,27 @@ postcss-modules-values@1.3.0: icss-replace-symbols "^1.1.0" postcss "^6.0.1" -postcss-modules@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules/-/postcss-modules-2.0.0.tgz#473d0d7326651d8408585c2a154115d5cb36cce0" - integrity sha512-eqp+Bva+U2cwQO7dECJ8/V+X+uH1HduNeITB0CPPFAu6d/8LKQ32/j+p9rQ2YL1QytVcrNU0X+fBqgGmQIA1Rw== +postcss-modules-values@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz#5b5000d6ebae29b4255301b4a3a54574423e7f10" + integrity sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg== + dependencies: + icss-utils "^4.0.0" + postcss "^7.0.6" + +postcss-modules@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/postcss-modules/-/postcss-modules-3.2.0.tgz#1ca870d197cd09a7964253e12de2aac906c94256" + integrity sha512-ceodlVbBypGD3R7EI1xM7gz28J0syaXq0VKd7rJVXVlOSkxUIRBRJQjBgpoKnKVFNAcCjtLVgZqBA3mUNntWPA== dependencies: - css-modules-loader-core "^1.1.0" generic-names "^2.0.1" + icss-replace-symbols "^1.1.0" lodash.camelcase "^4.3.0" - postcss "^7.0.1" + postcss "^7.0.32" + postcss-modules-extract-imports "^2.0.0" + postcss-modules-local-by-default "^3.0.2" + postcss-modules-scope "^2.2.0" + postcss-modules-values "^3.0.0" string-hash "^1.1.1" postcss-normalize-charset@^4.0.1: @@ -8563,7 +8693,7 @@ postcss-reduce-transforms@^4.0.2: postcss "^7.0.0" postcss-value-parser "^3.0.0" -postcss-selector-parser@6.0.2, postcss-selector-parser@^6.0.0: +postcss-selector-parser@6.0.2, postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz#934cf799d016c83411859e09dcecade01286ec5c" integrity sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg== @@ -8614,6 +8744,11 @@ postcss-value-parser@^3.0.0, postcss-value-parser@^3.3.1: resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== +postcss-value-parser@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb" + integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ== + postcss@6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.1.tgz#000dbd1f8eef217aa368b9a212c5fc40b2a8f3f2" @@ -8641,6 +8776,15 @@ postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.17, postcss@^7.0.5 source-map "^0.6.1" supports-color "^6.1.0" +postcss@^7.0.32, postcss@^7.0.6: + version "7.0.32" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.32.tgz#4310d6ee347053da3433db2be492883d62cec59d" + integrity sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw== + dependencies: + chalk "^2.4.2" + source-map "^0.6.1" + supports-color "^6.1.0" + posthtml-parser@^0.4.1: version "0.4.2" resolved "https://registry.yarnpkg.com/posthtml-parser/-/posthtml-parser-0.4.2.tgz#a132bbdf0cd4bc199d34f322f5c1599385d7c6c1" @@ -8701,12 +8845,12 @@ pretty-format@^25.2.1, pretty-format@^25.5.0: ansi-styles "^4.0.0" react-is "^16.12.0" -pretty-format@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.1.0.tgz#272b9cd1f1a924ab5d443dc224899d7a65cb96ec" - integrity sha512-GmeO1PEYdM+non4BKCj+XsPJjFOJIPnsLewqhDVoqY1xo0yNmDas7tC2XwpMrRAHR3MaE2hPo37deX5OisJ2Wg== +pretty-format@^26.2.0: + version "26.2.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.2.0.tgz#83ecc8d7de676ff224225055e72bd64821cec4f1" + integrity sha512-qi/8IuBu2clY9G7qCXgCdD1Bf9w+sXakdHTRToknzMtVy0g7c4MBWaZy7MfB7ndKZovRO6XRwJiAYqq+MC7SDA== dependencies: - "@jest/types" "^26.1.0" + "@jest/types" "^26.2.0" ansi-regex "^5.0.0" ansi-styles "^4.0.0" react-is "^16.12.0" @@ -9526,7 +9670,7 @@ snapdragon@^0.8.1: source-map-resolve "^0.5.0" use "^3.1.0" -source-map-resolve@^0.5.0, source-map-resolve@^0.5.2: +source-map-resolve@^0.5.0: version "0.5.3" resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== @@ -9537,6 +9681,14 @@ source-map-resolve@^0.5.0, source-map-resolve@^0.5.2: source-map-url "^0.4.0" urix "^0.1.0" +source-map-resolve@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.6.0.tgz#3d9df87e236b53f16d01e58150fc7711138e5ed2" + integrity sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w== + dependencies: + atob "^2.1.2" + decode-uri-component "^0.2.0" + source-map-support@^0.5.6: version "0.5.19" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" From 743da0c3d67b89d5249921decee5698b9323b378 Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Thu, 6 Aug 2020 14:49:42 +0800 Subject: [PATCH 076/116] Normalize wheel behavior across browsers (#117) --- src/layout/HorizontalPanAndZoomView.js | 4 +- src/layout/VerticalScrollView.js | 2 +- src/useCanvasInteraction.js | 29 ++++---- src/util/normalizeWheel.js | 99 ++++++++++++++++++++++++++ 4 files changed, 115 insertions(+), 19 deletions(-) create mode 100644 src/util/normalizeWheel.js diff --git a/src/layout/HorizontalPanAndZoomView.js b/src/layout/HorizontalPanAndZoomView.js index e8d04f1b77935..b6517af624689 100644 --- a/src/layout/HorizontalPanAndZoomView.js +++ b/src/layout/HorizontalPanAndZoomView.js @@ -179,7 +179,7 @@ export class HorizontalPanAndZoomView extends View { _handleWheelPlain(interaction: WheelPlainInteraction) { const { location, - event: {deltaX, deltaY}, + delta: {deltaX, deltaY}, } = interaction.payload; if (!rectContainsPoint(location, this.frame)) { return; // Not scrolling on view @@ -209,7 +209,7 @@ export class HorizontalPanAndZoomView extends View { ) { const { location, - event: {deltaY}, + delta: {deltaY}, } = interaction.payload; if (!rectContainsPoint(location, this.frame)) { return; // Not scrolling on view diff --git a/src/layout/VerticalScrollView.js b/src/layout/VerticalScrollView.js index 78baa9ef0b09b..4e72af1483164 100644 --- a/src/layout/VerticalScrollView.js +++ b/src/layout/VerticalScrollView.js @@ -116,7 +116,7 @@ export class VerticalScrollView extends View { _handleWheelPlain(interaction: WheelPlainInteraction) { const { location, - event: {deltaX, deltaY}, + delta: {deltaX, deltaY}, } = interaction.payload; if (!rectContainsPoint(location, this.frame)) { return; // Not scrolling on view diff --git a/src/useCanvasInteraction.js b/src/useCanvasInteraction.js index fd85e37e4d909..ac1af7a8afc14 100644 --- a/src/useCanvasInteraction.js +++ b/src/useCanvasInteraction.js @@ -1,8 +1,10 @@ // @flow import type {Point} from './layout'; +import type {NormalizedWheelDelta} from './util/normalizeWheel'; import {useEffect} from 'react'; +import {normalizeWheel} from './util/normalizeWheel'; export type MouseDownInteraction = {| type: 'mousedown', @@ -30,6 +32,7 @@ export type WheelPlainInteraction = {| payload: {| event: WheelEvent, location: Point, + delta: NormalizedWheelDelta, |}, |}; export type WheelWithShiftInteraction = {| @@ -37,6 +40,7 @@ export type WheelWithShiftInteraction = {| payload: {| event: WheelEvent, location: Point, + delta: NormalizedWheelDelta, |}, |}; export type WheelWithControlInteraction = {| @@ -44,6 +48,7 @@ export type WheelWithControlInteraction = {| payload: {| event: WheelEvent, location: Point, + delta: NormalizedWheelDelta, |}, |}; export type WheelWithMetaInteraction = {| @@ -51,6 +56,7 @@ export type WheelWithMetaInteraction = {| payload: {| event: WheelEvent, location: Point, + delta: NormalizedWheelDelta, |}, |}; @@ -137,37 +143,28 @@ export function useCanvasInteraction( event.preventDefault(); event.stopPropagation(); + const location = localToCanvasCoordinates({x: event.x, y: event.y}); + const delta = normalizeWheel(event); + if (event.shiftKey) { interactor({ type: 'wheel-shift', - payload: { - event, - location: localToCanvasCoordinates({x: event.x, y: event.y}), - }, + payload: {event, location, delta}, }); } else if (event.ctrlKey) { interactor({ type: 'wheel-control', - payload: { - event, - location: localToCanvasCoordinates({x: event.x, y: event.y}), - }, + payload: {event, location, delta}, }); } else if (event.metaKey) { interactor({ type: 'wheel-meta', - payload: { - event, - location: localToCanvasCoordinates({x: event.x, y: event.y}), - }, + payload: {event, location, delta}, }); } else { interactor({ type: 'wheel-plain', - payload: { - event, - location: localToCanvasCoordinates({x: event.x, y: event.y}), - }, + payload: {event, location, delta}, }); } diff --git a/src/util/normalizeWheel.js b/src/util/normalizeWheel.js new file mode 100644 index 0000000000000..13c650eba8946 --- /dev/null +++ b/src/util/normalizeWheel.js @@ -0,0 +1,99 @@ +/** + * Copyright (c) 2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in + * https://github.com/facebookarchive/fixed-data-table/blob/master/LICENSE. + * An additional grant of patent rights can be found in the PATENTS file in the + * same directory. + * + * Adapted from: https://github.com/facebookarchive/fixed-data-table/blob/master/src/vendor_upstream/dom/normalizeWheel.js + * + * TODO: Figure out the license of this code. It was originally licensed by + * Facebook with a BSD-style license. Since this profiler project is going into + * another Facebook repository, I suppose we can just relicense it under + * React's license? + * + * @flow + */ + +export type NormalizedWheelDelta = {| + deltaX: number, + deltaY: number, +|}; + +// Reasonable defaults +const LINE_HEIGHT = 40; +const PAGE_HEIGHT = 800; + +/** + * Mouse wheel (and 2-finger trackpad) support on the web sucks. It is + * complicated, thus this doc is long and (hopefully) detailed enough to answer + * your questions. + * + * If you need to react to the mouse wheel in a predictable way, this code is + * like your bestest friend. * hugs * + * + * In your event callback, use this code to get sane interpretation of the + * deltas. This code will return an object with properties: + * + * - deltaX -- normalized distance (to pixels) - x plane + * - deltaY -- " - y plane + * + * Wheel values are provided by the browser assuming you are using the wheel to + * scroll a web page by a number of lines or pixels (or pages). Values can vary + * significantly on different platforms and browsers, forgetting that you can + * scroll at different speeds. Some devices (like trackpads) emit more events + * at smaller increments with fine granularity, and some emit massive jumps with + * linear speed or acceleration. + * + * This code does its best to normalize the deltas for you: + * + * - delta* is normalizing the desired scroll delta in pixel units. + * + * - positive value indicates scrolling DOWN/RIGHT, negative UP/LEFT. This + * should translate to positive value zooming IN, negative zooming OUT. + * This matches the 'wheel' event. + * + * Implementation info: + * + * The basics of the standard 'wheel' event is that it includes a unit, + * deltaMode (pixels, lines, pages), and deltaX, deltaY and deltaZ. + * See: http://www.w3.org/TR/DOM-Level-3-Events/#events-wheelevents + * + * Examples of 'wheel' event if you scroll slowly (down) by one step with an + * average mouse: + * + * OS X + Chrome (mouse) - 4 pixel delta (wheelDelta -120) + * OS X + Safari (mouse) - N/A pixel delta (wheelDelta -12) + * OS X + Firefox (mouse) - 0.1 line delta (wheelDelta N/A) + * Win8 + Chrome (mouse) - 100 pixel delta (wheelDelta -120) + * Win8 + Firefox (mouse) - 3 line delta (wheelDelta -120) + * + * On the trackpad: + * + * OS X + Chrome (trackpad) - 2 pixel delta (wheelDelta -6) + * OS X + Firefox (trackpad) - 1 pixel delta (wheelDelta N/A) + */ +export function normalizeWheel(event: WheelEvent): NormalizedWheelDelta { + let deltaX = event.deltaX; + let deltaY = event.deltaY; + + if ( + // $FlowFixMe DOM_DELTA_LINE missing from WheelEvent + event.deltaMode === WheelEvent.DOM_DELTA_LINE + ) { + // delta in LINE units + deltaX *= LINE_HEIGHT; + deltaY *= LINE_HEIGHT; + } else if ( + // $FlowFixMe DOM_DELTA_PAGE missing from WheelEvent + event.deltaMode === WheelEvent.DOM_DELTA_PAGE + ) { + // delta in PAGE units + deltaX *= PAGE_HEIGHT; + deltaY *= PAGE_HEIGHT; + } + + return {deltaX, deltaY}; +} From 92f47508cfd51c342f8ad14aa291a4acecdef5f5 Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Thu, 6 Aug 2020 22:07:17 +0800 Subject: [PATCH 077/116] Reorganize layout and canvas folders (#120) --- src/CanvasPage.js | 15 ++- src/EventTooltip.js | 8 +- src/ImportPage.js | 4 +- src/canvas/canvasUtils.js | 104 ------------------ .../views => content-views}/FlamechartView.js | 46 +++++--- .../ReactEventsView.js | 36 +++--- .../ReactMeasuresView.js | 27 ++--- .../TimeAxisMarkersView.js | 25 ++--- .../UserTimingMarksView.js | 37 +++---- src/{canvas => content-views}/constants.js | 38 +------ src/{canvas/views => content-views}/index.js | 0 .../utils}/__tests__/colors-test.js | 0 src/{canvas => content-views/utils}/colors.js | 0 src/content-views/utils/positioning.js | 34 ++++++ .../__snapshots__/preprocessData-test.js.snap | 0 .../__tests__/preprocessData-test.js | 0 src/{util => utils}/getBatchRange.js | 0 src/{util => utils}/preprocessData.js | 0 src/{util => utils}/readInputData.js | 0 src/{util => utils}/useSmartTooltip.js | 0 src/{layout => view-base}/ColorView.js | 0 .../HorizontalPanAndZoomView.js | 4 +- .../ResizableSplitView.js | 2 +- src/{layout => view-base}/Surface.js | 31 +++++- .../VerticalScrollView.js | 4 +- src/{layout => view-base}/View.js | 2 +- .../__tests__/geometry-test.js | 0 src/view-base/constants.js | 4 + src/{layout => view-base}/geometry.js | 0 src/{layout => view-base}/index.js | 1 + src/{layout => view-base}/layouter.js | 0 src/{ => view-base}/useCanvasInteraction.js | 6 +- .../utils}/normalizeWheel.js | 0 33 files changed, 183 insertions(+), 245 deletions(-) delete mode 100644 src/canvas/canvasUtils.js rename src/{canvas/views => content-views}/FlamechartView.js (90%) rename src/{canvas/views => content-views}/ReactEventsView.js (89%) rename src/{canvas/views => content-views}/ReactMeasuresView.js (93%) rename src/{canvas/views => content-views}/TimeAxisMarkersView.js (91%) rename src/{canvas/views => content-views}/UserTimingMarksView.js (86%) rename src/{canvas => content-views}/constants.js (54%) rename src/{canvas/views => content-views}/index.js (100%) rename src/{canvas => content-views/utils}/__tests__/colors-test.js (100%) rename src/{canvas => content-views/utils}/colors.js (100%) create mode 100644 src/content-views/utils/positioning.js rename src/{util => utils}/__tests__/__snapshots__/preprocessData-test.js.snap (100%) rename src/{util => utils}/__tests__/preprocessData-test.js (100%) rename src/{util => utils}/getBatchRange.js (100%) rename src/{util => utils}/preprocessData.js (100%) rename src/{util => utils}/readInputData.js (100%) rename src/{util => utils}/useSmartTooltip.js (100%) rename src/{layout => view-base}/ColorView.js (100%) rename src/{layout => view-base}/HorizontalPanAndZoomView.js (98%) rename src/{layout => view-base}/ResizableSplitView.js (99%) rename src/{layout => view-base}/Surface.js (56%) rename src/{layout => view-base}/VerticalScrollView.js (96%) rename src/{layout => view-base}/View.js (99%) rename src/{layout => view-base}/__tests__/geometry-test.js (100%) create mode 100644 src/view-base/constants.js rename src/{layout => view-base}/geometry.js (100%) rename src/{layout => view-base}/index.js (86%) rename src/{layout => view-base}/layouter.js (100%) rename src/{ => view-base}/useCanvasInteraction.js (96%) rename src/{util => view-base/utils}/normalizeWheel.js (100%) diff --git a/src/CanvasPage.js b/src/CanvasPage.js index 3590da30414e5..227797bf09223 100644 --- a/src/CanvasPage.js +++ b/src/CanvasPage.js @@ -1,6 +1,9 @@ // @flow -import type {Point, HorizontalPanAndZoomViewOnChangeCallback} from './layout'; +import type { + Point, + HorizontalPanAndZoomViewOnChangeCallback, +} from './view-base'; import {copy} from 'clipboard-js'; import React, { @@ -20,30 +23,30 @@ import { View, createComposedLayout, lastViewTakesUpRemainingSpaceLayout, + useCanvasInteraction, verticallyStackedLayout, zeroPoint, -} from './layout'; +} from './view-base'; import prettyMilliseconds from 'pretty-ms'; -import {getBatchRange} from './util/getBatchRange'; +import {getBatchRange} from './utils/getBatchRange'; import EventTooltip from './EventTooltip'; import styles from './CanvasPage.css'; import AutoSizer from 'react-virtualized-auto-sizer'; -import {COLORS} from './canvas/constants'; +import {COLORS} from './content-views/constants'; import {ContextMenu, ContextMenuItem, useContextMenu} from './context'; const CONTEXT_MENU_ID = 'canvas'; import type {ReactHoverContextInfo, ReactProfilerData} from './types'; -import {useCanvasInteraction} from './useCanvasInteraction'; import { FlamechartView, ReactEventsView, ReactMeasuresView, TimeAxisMarkersView, UserTimingMarksView, -} from './canvas/views'; +} from './content-views'; type ContextMenuContextData = {| data: ReactProfilerData, diff --git a/src/EventTooltip.js b/src/EventTooltip.js index 37ba646da8d92..da94f3800e503 100644 --- a/src/EventTooltip.js +++ b/src/EventTooltip.js @@ -1,6 +1,6 @@ // @flow -import type {Point} from './layout'; +import type {Point} from './view-base'; import type { FlamechartStackFrame, ReactEvent, @@ -13,9 +13,9 @@ import type { import prettyMilliseconds from 'pretty-ms'; import React, {Fragment, useRef} from 'react'; -import {COLORS} from './canvas/constants'; -import {getBatchRange} from './util/getBatchRange'; -import useSmartTooltip from './util/useSmartTooltip'; +import {COLORS} from './content-views/constants'; +import {getBatchRange} from './utils/getBatchRange'; +import useSmartTooltip from './utils/useSmartTooltip'; import styles from './EventTooltip.css'; type Props = {| diff --git a/src/ImportPage.js b/src/ImportPage.js index 23be7afadee4e..3a3d83385f72d 100644 --- a/src/ImportPage.js +++ b/src/ImportPage.js @@ -7,8 +7,8 @@ import React, {useEffect, useCallback, useRef} from 'react'; import profilerBrowser from './assets/profilerBrowser.png'; import style from './ImportPage.css'; -import preprocessData from './util/preprocessData'; -import {readInputData} from './util/readInputData'; +import preprocessData from './utils/preprocessData'; +import {readInputData} from './utils/readInputData'; // TODO: Use for dev only, switch to import file after import JSON_PATH from 'url:../static/perfprofilev2.json'; diff --git a/src/canvas/canvasUtils.js b/src/canvas/canvasUtils.js deleted file mode 100644 index f2dc6e9c669c7..0000000000000 --- a/src/canvas/canvasUtils.js +++ /dev/null @@ -1,104 +0,0 @@ -// @flow -// Contains helper functions for rendering canvas elements - -import type {Rect} from '../layout'; - -import memoize from 'memoize-one'; -import {INTERVAL_TIMES, MAX_INTERVAL_SIZE_PX} from './constants'; - -// hidpi canvas: https://www.html5rocks.com/en/tutorials/canvas/hidpi/ -function configureRetinaCanvas(canvas, height, width) { - const dpr: number = window.devicePixelRatio || 1; - canvas.width = width * dpr; - canvas.height = height * dpr; - canvas.style.width = `${width}px`; - canvas.style.height = `${height}px`; - return dpr; -} - -export const getCanvasContext = memoize( - ( - canvas: HTMLCanvasElement, - height: number, - width: number, - scaleCanvas: boolean = true, - ): CanvasRenderingContext2D => { - const context = canvas.getContext('2d', {alpha: false}); - if (scaleCanvas) { - const dpr = configureRetinaCanvas(canvas, height, width); - // Scale all drawing operations by the dpr, so you don't have to worry about the difference. - context.scale(dpr, dpr); - } - return context; - }, -); - -// Time mark intervals vary based on the current zoom range and the time it represents. -// In Chrome, these seem to range from 70-140 pixels wide. -// Time wise, they represent intervals of e.g. 1s, 500ms, 200ms, 100ms, 50ms, 20ms. -// Based on zoom, we should determine which amount to actually show. -export function getTimeTickInterval(zoomLevel: number) { - let interval = INTERVAL_TIMES[0]; - for (let i = 0; i < INTERVAL_TIMES.length; i++) { - const currentInterval = INTERVAL_TIMES[i]; - const pixels = currentInterval * zoomLevel; - if (pixels <= MAX_INTERVAL_SIZE_PX) { - interval = currentInterval; - } - } - return interval; -} - -const cachedFlamechartTextWidths = new Map(); -export const trimFlamechartText = ( - context: CanvasRenderingContext2D, - text: string, - width: number, -) => { - for (let i = text.length - 1; i >= 0; i--) { - const trimmedText = i === text.length - 1 ? text : text.substr(0, i) + '…'; - - let measuredWidth = cachedFlamechartTextWidths.get(trimmedText); - if (measuredWidth == null) { - measuredWidth = context.measureText(trimmedText).width; - cachedFlamechartTextWidths.set(trimmedText, measuredWidth); - } - - if (measuredWidth <= width) { - return trimmedText; - } - } - - return null; -}; - -export function positioningScaleFactor( - intrinsicWidth: number, - frame: Rect, -): number { - return frame.size.width / intrinsicWidth; -} - -export function timestampToPosition( - timestamp: number, - scaleFactor: number, - frame: Rect, -): number { - return frame.origin.x + timestamp * scaleFactor; -} - -export function positionToTimestamp( - position: number, - scaleFactor: number, - frame: Rect, -): number { - return (position - frame.origin.x) / scaleFactor; -} - -export function durationToWidth(duration: number, scaleFactor: number): number { - return duration * scaleFactor; -} - -export function widthToDuration(width: number, scaleFactor: number): number { - return width / scaleFactor; -} diff --git a/src/canvas/views/FlamechartView.js b/src/content-views/FlamechartView.js similarity index 90% rename from src/canvas/views/FlamechartView.js rename to src/content-views/FlamechartView.js index 585d7f589b670..3dfd54026d25b 100644 --- a/src/canvas/views/FlamechartView.js +++ b/src/content-views/FlamechartView.js @@ -1,15 +1,11 @@ // @flow -import type { - Interaction, - MouseMoveInteraction, -} from '../../useCanvasInteraction'; import type { Flamechart, FlamechartStackFrame, FlamechartStackLayer, -} from '../../types'; -import type {Rect, Size} from '../../layout'; +} from '../types'; +import type {Interaction, MouseMoveInteraction, Rect, Size} from '../view-base'; import { ColorView, @@ -21,22 +17,21 @@ import { rectIntersectionWithRect, rectIntersectsRect, verticallyStackedLayout, -} from '../../layout'; +} from '../view-base'; import { durationToWidth, positioningScaleFactor, timestampToPosition, - trimFlamechartText, -} from '../canvasUtils'; +} from './utils/positioning'; import { COLORS, FLAMECHART_FONT_SIZE, FLAMECHART_FRAME_HEIGHT, FLAMECHART_TEXT_PADDING, COLOR_HOVER_DIM_DELTA, - REACT_WORK_BORDER_SIZE, -} from '../constants'; -import {ColorGenerator, dimmedColor, hslaColorToString} from '../colors'; + BORDER_SIZE, +} from './constants'; +import {ColorGenerator, dimmedColor, hslaColorToString} from './utils/colors'; // Source: https://source.chromium.org/chromium/chromium/src/+/master:out/Debug/gen/devtools/timeline/TimelineUIUtils.js;l=2109;drc=fb32e928d79707a693351b806b8710b2f6b7d399 const colorGenerator = new ColorGenerator( @@ -63,6 +58,29 @@ function hoverColorForStackFrame(stackFrame: FlamechartStackFrame): string { return hslaColorToString(color); } +const cachedFlamechartTextWidths = new Map(); +const trimFlamechartText = ( + context: CanvasRenderingContext2D, + text: string, + width: number, +) => { + for (let i = text.length - 1; i >= 0; i--) { + const trimmedText = i === text.length - 1 ? text : text.substr(0, i) + '…'; + + let measuredWidth = cachedFlamechartTextWidths.get(trimmedText); + if (measuredWidth == null) { + measuredWidth = context.measureText(trimmedText).width; + cachedFlamechartTextWidths.set(trimmedText, measuredWidth); + } + + if (measuredWidth <= width) { + return trimmedText; + } + } + + return null; +}; + class FlamechartStackLayerView extends View { /** Layer to display */ _stackLayer: FlamechartStackLayer; @@ -149,8 +167,8 @@ class FlamechartStackLayerView extends View { const nodeRect: Rect = { origin: {x, y: frame.origin.y}, size: { - width: Math.floor(width - REACT_WORK_BORDER_SIZE), - height: Math.floor(FLAMECHART_FRAME_HEIGHT - REACT_WORK_BORDER_SIZE), + width: Math.floor(width - BORDER_SIZE), + height: Math.floor(FLAMECHART_FRAME_HEIGHT - BORDER_SIZE), }, }; if (!rectIntersectsRect(nodeRect, visibleArea)) { diff --git a/src/canvas/views/ReactEventsView.js b/src/content-views/ReactEventsView.js similarity index 89% rename from src/canvas/views/ReactEventsView.js rename to src/content-views/ReactEventsView.js index e73c837490d09..68b35ca1fb31b 100644 --- a/src/canvas/views/ReactEventsView.js +++ b/src/content-views/ReactEventsView.js @@ -1,32 +1,30 @@ // @flow -import type { - Interaction, - MouseMoveInteraction, -} from '../../useCanvasInteraction'; -import type {ReactEvent, ReactProfilerData} from '../../types'; -import type {Rect, Size} from '../../layout'; +import type {ReactEvent, ReactProfilerData} from '../types'; +import type {Interaction, MouseMoveInteraction, Rect, Size} from '../view-base'; import { positioningScaleFactor, timestampToPosition, positionToTimestamp, widthToDuration, -} from '../canvasUtils'; +} from './utils/positioning'; import { View, Surface, rectContainsPoint, rectIntersectsRect, rectIntersectionWithRect, -} from '../../layout'; +} from '../view-base'; import { COLORS, - EVENT_ROW_HEIGHT_FIXED, - REACT_EVENT_ROW_PADDING, - REACT_EVENT_SIZE, - REACT_WORK_BORDER_SIZE, -} from '../constants'; + EVENT_ROW_PADDING, + EVENT_DIAMETER, + BORDER_SIZE, +} from './constants'; + +const EVENT_ROW_HEIGHT_FIXED = + EVENT_ROW_PADDING + EVENT_DIAMETER + EVENT_ROW_PADDING; function isSuspenseEvent(event: ReactEvent): boolean %checks { return ( @@ -80,13 +78,13 @@ export class ReactEventsView extends View { const {timestamp, type} = event; const x = timestampToPosition(timestamp, scaleFactor, frame); - const radius = REACT_EVENT_SIZE / 2; + const radius = EVENT_DIAMETER / 2; const eventRect: Rect = { origin: { x: x - radius, y: baseY, }, - size: {width: REACT_EVENT_SIZE, height: REACT_EVENT_SIZE}, + size: {width: EVENT_DIAMETER, height: EVENT_DIAMETER}, }; if (!rectIntersectsRect(eventRect, rect)) { return; // Not in view @@ -147,7 +145,7 @@ export class ReactEventsView extends View { ); // Draw events - const baseY = frame.origin.y + REACT_EVENT_ROW_PADDING; + const baseY = frame.origin.y + EVENT_ROW_PADDING; const scaleFactor = positioningScaleFactor( this._intrinsicSize.width, frame, @@ -194,11 +192,11 @@ export class ReactEventsView extends View { const borderFrame: Rect = { origin: { x: frame.origin.x, - y: frame.origin.y + EVENT_ROW_HEIGHT_FIXED - REACT_WORK_BORDER_SIZE, + y: frame.origin.y + EVENT_ROW_HEIGHT_FIXED - BORDER_SIZE, }, size: { width: frame.size.width, - height: REACT_WORK_BORDER_SIZE, + height: BORDER_SIZE, }, }; if (rectIntersectsRect(borderFrame, visibleArea)) { @@ -240,7 +238,7 @@ export class ReactEventsView extends View { ); const hoverTimestamp = positionToTimestamp(location.x, scaleFactor, frame); const eventTimestampAllowance = widthToDuration( - REACT_EVENT_SIZE / 2, + EVENT_DIAMETER / 2, scaleFactor, ); diff --git a/src/canvas/views/ReactMeasuresView.js b/src/content-views/ReactMeasuresView.js similarity index 93% rename from src/canvas/views/ReactMeasuresView.js rename to src/content-views/ReactMeasuresView.js index 317e9a3647aca..20837ea5594d4 100644 --- a/src/canvas/views/ReactMeasuresView.js +++ b/src/content-views/ReactMeasuresView.js @@ -1,30 +1,26 @@ // @flow -import type { - Interaction, - MouseMoveInteraction, -} from '../../useCanvasInteraction'; -import type {ReactLane, ReactMeasure, ReactProfilerData} from '../../types'; -import type {Rect, Size} from '../../layout'; +import type {ReactLane, ReactMeasure, ReactProfilerData} from '../types'; +import type {Interaction, MouseMoveInteraction, Rect, Size} from '../view-base'; import { durationToWidth, positioningScaleFactor, positionToTimestamp, timestampToPosition, -} from '../canvasUtils'; +} from './utils/positioning'; import { View, Surface, rectContainsPoint, rectIntersectsRect, rectIntersectionWithRect, -} from '../../layout'; +} from '../view-base'; -import {COLORS, REACT_WORK_BORDER_SIZE, REACT_WORK_SIZE} from '../constants'; -import {REACT_TOTAL_NUM_LANES} from '../../constants'; +import {COLORS, BORDER_SIZE, REACT_MEASURE_HEIGHT} from './constants'; +import {REACT_TOTAL_NUM_LANES} from '../constants'; -const REACT_LANE_HEIGHT = REACT_WORK_SIZE + REACT_WORK_BORDER_SIZE; +const REACT_LANE_HEIGHT = REACT_MEASURE_HEIGHT + BORDER_SIZE; export class ReactMeasuresView extends View { _profilerData: ReactProfilerData; @@ -105,7 +101,7 @@ export class ReactMeasuresView extends View { const x = timestampToPosition(timestamp, scaleFactor, frame); const measureRect: Rect = { origin: {x, y: baseY}, - size: {width, height: REACT_WORK_SIZE}, + size: {width, height: REACT_MEASURE_HEIGHT}, }; if (!rectIntersectsRect(measureRect, rect)) { return; // Not in view @@ -213,14 +209,11 @@ export class ReactMeasuresView extends View { const borderFrame: Rect = { origin: { x: frame.origin.x, - y: - frame.origin.y + - (i + 1) * REACT_LANE_HEIGHT - - REACT_WORK_BORDER_SIZE, + y: frame.origin.y + (i + 1) * REACT_LANE_HEIGHT - BORDER_SIZE, }, size: { width: frame.size.width, - height: REACT_WORK_BORDER_SIZE, + height: BORDER_SIZE, }, }; if (rectIntersectsRect(borderFrame, visibleArea)) { diff --git a/src/canvas/views/TimeAxisMarkersView.js b/src/content-views/TimeAxisMarkersView.js similarity index 91% rename from src/canvas/views/TimeAxisMarkersView.js rename to src/content-views/TimeAxisMarkersView.js index 0dcfbb4e3883d..39560e8439fb7 100644 --- a/src/canvas/views/TimeAxisMarkersView.js +++ b/src/content-views/TimeAxisMarkersView.js @@ -1,31 +1,33 @@ // @flow -import type {Rect, Size} from '../../layout'; +import type {Rect, Size} from '../view-base'; import { durationToWidth, positioningScaleFactor, positionToTimestamp, timestampToPosition, -} from '../canvasUtils'; +} from './utils/positioning'; import { View, Surface, rectIntersectsRect, rectIntersectionWithRect, -} from '../../layout'; +} from '../view-base'; import { COLORS, - HEADER_HEIGHT_FIXED, INTERVAL_TIMES, - LABEL_FIXED_WIDTH, + LABEL_SIZE, MARKER_FONT_SIZE, MARKER_HEIGHT, MARKER_TEXT_PADDING, MARKER_TICK_HEIGHT, MIN_INTERVAL_SIZE_PX, - REACT_WORK_BORDER_SIZE, -} from '../constants'; + BORDER_SIZE, +} from './constants'; + +const HEADER_HEIGHT_FIXED = MARKER_HEIGHT + BORDER_SIZE; +const LABEL_FIXED_WIDTH = LABEL_SIZE + BORDER_SIZE; export class TimeAxisMarkersView extends View { _totalDuration: number; @@ -113,7 +115,7 @@ export class TimeAxisMarkersView extends View { context.fillRect( x, drawableRect.origin.y + MARKER_HEIGHT - MARKER_TICK_HEIGHT, - REACT_WORK_BORDER_SIZE, + BORDER_SIZE, MARKER_TICK_HEIGHT, ); @@ -133,14 +135,11 @@ export class TimeAxisMarkersView extends View { const borderFrame: Rect = { origin: { x: clippedFrame.origin.x, - y: - clippedFrame.origin.y + - clippedFrame.size.height - - REACT_WORK_BORDER_SIZE, + y: clippedFrame.origin.y + clippedFrame.size.height - BORDER_SIZE, }, size: { width: clippedFrame.size.width, - height: REACT_WORK_BORDER_SIZE, + height: BORDER_SIZE, }, }; if (rectIntersectsRect(borderFrame, visibleArea)) { diff --git a/src/canvas/views/UserTimingMarksView.js b/src/content-views/UserTimingMarksView.js similarity index 86% rename from src/canvas/views/UserTimingMarksView.js rename to src/content-views/UserTimingMarksView.js index 0cf3ad6099c8e..7f768dddbcf67 100644 --- a/src/canvas/views/UserTimingMarksView.js +++ b/src/content-views/UserTimingMarksView.js @@ -1,34 +1,29 @@ // @flow -import type { - Interaction, - MouseMoveInteraction, -} from '../../useCanvasInteraction'; -import type {UserTimingMark} from '../../types'; -import type {Rect, Size} from '../../layout'; +import type {UserTimingMark} from '../types'; +import type {Interaction, MouseMoveInteraction, Rect, Size} from '../view-base'; import { positioningScaleFactor, timestampToPosition, positionToTimestamp, widthToDuration, -} from '../canvasUtils'; +} from './utils/positioning'; import { View, Surface, rectContainsPoint, rectIntersectsRect, rectIntersectionWithRect, -} from '../../layout'; +} from '../view-base'; import { COLORS, - EVENT_ROW_HEIGHT_FIXED, - REACT_EVENT_ROW_PADDING, - REACT_EVENT_SIZE, - REACT_WORK_BORDER_SIZE, -} from '../constants'; + EVENT_ROW_PADDING, + EVENT_DIAMETER, + BORDER_SIZE, +} from './constants'; -// COMBAK: use this viewA +const ROW_HEIGHT_FIXED = EVENT_ROW_PADDING + EVENT_DIAMETER + EVENT_ROW_PADDING; export class UserTimingMarksView extends View { _marks: UserTimingMark[]; @@ -48,7 +43,7 @@ export class UserTimingMarksView extends View { this._intrinsicSize = { width: duration, - height: EVENT_ROW_HEIGHT_FIXED, + height: ROW_HEIGHT_FIXED, }; } @@ -79,13 +74,13 @@ export class UserTimingMarksView extends View { const {timestamp} = mark; const x = timestampToPosition(timestamp, scaleFactor, frame); - const radius = REACT_EVENT_SIZE / 2; + const radius = EVENT_DIAMETER / 2; const markRect: Rect = { origin: { x: x - radius, y: baseY, }, - size: {width: REACT_EVENT_SIZE, height: REACT_EVENT_SIZE}, + size: {width: EVENT_DIAMETER, height: EVENT_DIAMETER}, }; if (!rectIntersectsRect(markRect, rect)) { return; // Not in view @@ -118,7 +113,7 @@ export class UserTimingMarksView extends View { ); // Draw marks - const baseY = frame.origin.y + REACT_EVENT_ROW_PADDING; + const baseY = frame.origin.y + EVENT_ROW_PADDING; const scaleFactor = positioningScaleFactor( this._intrinsicSize.width, frame, @@ -156,11 +151,11 @@ export class UserTimingMarksView extends View { const borderFrame: Rect = { origin: { x: frame.origin.x, - y: frame.origin.y + EVENT_ROW_HEIGHT_FIXED - REACT_WORK_BORDER_SIZE, + y: frame.origin.y + ROW_HEIGHT_FIXED - BORDER_SIZE, }, size: { width: frame.size.width, - height: REACT_WORK_BORDER_SIZE, + height: BORDER_SIZE, }, }; if (rectIntersectsRect(borderFrame, visibleArea)) { @@ -200,7 +195,7 @@ export class UserTimingMarksView extends View { ); const hoverTimestamp = positionToTimestamp(location.x, scaleFactor, frame); const markTimestampAllowance = widthToDuration( - REACT_EVENT_SIZE / 2, + EVENT_DIAMETER / 2, scaleFactor, ); diff --git a/src/canvas/constants.js b/src/content-views/constants.js similarity index 54% rename from src/canvas/constants.js rename to src/content-views/constants.js index d10d138e97902..1dd70c02611de 100644 --- a/src/canvas/constants.js +++ b/src/content-views/constants.js @@ -5,13 +5,7 @@ export const LABEL_FONT_SIZE = 11; export const MARKER_HEIGHT = 20; export const MARKER_TICK_HEIGHT = 8; export const MARKER_FONT_SIZE = 10; -export const MARKER_GUTTER_SIZE = 4; export const MARKER_TEXT_PADDING = 8; -export const BAR_HEIGHT = 16; -export const BAR_HORIZONTAL_SPACING = 1; -export const BAR_SPACER_SIZE = 6; -export const MIN_BAR_WIDTH = 1; -export const SECTION_GUTTER_SIZE = 4; export const COLOR_HOVER_DIM_DELTA = 5; export const INTERVAL_TIMES = [ @@ -29,41 +23,18 @@ export const INTERVAL_TIMES = [ 5000, ]; export const MIN_INTERVAL_SIZE_PX = 70; -export const MAX_INTERVAL_SIZE_PX = 140; -export const MOVE_WHEEL_DELTA_THRESHOLD = 1; -export const ZOOM_WHEEL_DELTA_THRESHOLD = 1; -export const MIN_ZOOM_LEVEL = 0.25; -export const MAX_ZOOM_LEVEL = 1000; - -export const REACT_PRIORITIES = ['unscheduled', 'high', 'normal', 'low']; - -export const ROW_CSS_PIXELS_HEIGHT = 16; -export const TEXT_CSS_PIXELS_OFFSET_START = 3; -export const TEXT_CSS_PIXELS_OFFSET_TOP = 11; -export const FONT_SIZE = 10; -export const BORDER_OPACITY = 0.4; - -export const REACT_GUTTER_SIZE = 0; // Increase to add vertical padding to lanes -export const REACT_EVENT_ROW_PADDING = 4; -export const REACT_EVENT_SIZE = 6; -export const REACT_WORK_SIZE = 9; -export const REACT_EVENT_BORDER_SIZE = 1; -export const REACT_WORK_BORDER_SIZE = 1; +export const EVENT_ROW_PADDING = 4; +export const EVENT_DIAMETER = 6; +export const REACT_MEASURE_HEIGHT = 9; +export const BORDER_SIZE = 1; export const FLAMECHART_FONT_SIZE = 10; export const FLAMECHART_FRAME_HEIGHT = 16; export const FLAMECHART_TEXT_PADDING = 3; -export const LABEL_FIXED_WIDTH = LABEL_SIZE + REACT_WORK_BORDER_SIZE; -export const HEADER_HEIGHT_FIXED = MARKER_HEIGHT + REACT_WORK_BORDER_SIZE; -export const EVENT_ROW_HEIGHT_FIXED = - REACT_EVENT_ROW_PADDING + REACT_EVENT_SIZE + REACT_EVENT_ROW_PADDING; - export const COLORS = Object.freeze({ BACKGROUND: '#ffffff', - OTHER_SCRIPT: '#fff791', - OTHER_SCRIPT_HOVER: '#ffea00', PRIORITY_BACKGROUND: '#ededf0', PRIORITY_BORDER: '#d7d7db', PRIORITY_LABEL: '#272727', @@ -91,6 +62,5 @@ export const COLORS = Object.freeze({ REACT_SUSPEND: '#a6e59f', REACT_SUSPEND_HOVER: '#13bc00', REACT_WORK_BORDER: '#ffffff', - TIME_MARKER_LINE: '#CAD6DE', TIME_MARKER_LABEL: '#18212b', }); diff --git a/src/canvas/views/index.js b/src/content-views/index.js similarity index 100% rename from src/canvas/views/index.js rename to src/content-views/index.js diff --git a/src/canvas/__tests__/colors-test.js b/src/content-views/utils/__tests__/colors-test.js similarity index 100% rename from src/canvas/__tests__/colors-test.js rename to src/content-views/utils/__tests__/colors-test.js diff --git a/src/canvas/colors.js b/src/content-views/utils/colors.js similarity index 100% rename from src/canvas/colors.js rename to src/content-views/utils/colors.js diff --git a/src/content-views/utils/positioning.js b/src/content-views/utils/positioning.js new file mode 100644 index 0000000000000..a6e0e09c3efe6 --- /dev/null +++ b/src/content-views/utils/positioning.js @@ -0,0 +1,34 @@ +// @flow + +import type {Rect} from '../../view-base'; + +export function positioningScaleFactor( + intrinsicWidth: number, + frame: Rect, +): number { + return frame.size.width / intrinsicWidth; +} + +export function timestampToPosition( + timestamp: number, + scaleFactor: number, + frame: Rect, +): number { + return frame.origin.x + timestamp * scaleFactor; +} + +export function positionToTimestamp( + position: number, + scaleFactor: number, + frame: Rect, +): number { + return (position - frame.origin.x) / scaleFactor; +} + +export function durationToWidth(duration: number, scaleFactor: number): number { + return duration * scaleFactor; +} + +export function widthToDuration(width: number, scaleFactor: number): number { + return width / scaleFactor; +} diff --git a/src/util/__tests__/__snapshots__/preprocessData-test.js.snap b/src/utils/__tests__/__snapshots__/preprocessData-test.js.snap similarity index 100% rename from src/util/__tests__/__snapshots__/preprocessData-test.js.snap rename to src/utils/__tests__/__snapshots__/preprocessData-test.js.snap diff --git a/src/util/__tests__/preprocessData-test.js b/src/utils/__tests__/preprocessData-test.js similarity index 100% rename from src/util/__tests__/preprocessData-test.js rename to src/utils/__tests__/preprocessData-test.js diff --git a/src/util/getBatchRange.js b/src/utils/getBatchRange.js similarity index 100% rename from src/util/getBatchRange.js rename to src/utils/getBatchRange.js diff --git a/src/util/preprocessData.js b/src/utils/preprocessData.js similarity index 100% rename from src/util/preprocessData.js rename to src/utils/preprocessData.js diff --git a/src/util/readInputData.js b/src/utils/readInputData.js similarity index 100% rename from src/util/readInputData.js rename to src/utils/readInputData.js diff --git a/src/util/useSmartTooltip.js b/src/utils/useSmartTooltip.js similarity index 100% rename from src/util/useSmartTooltip.js rename to src/utils/useSmartTooltip.js diff --git a/src/layout/ColorView.js b/src/view-base/ColorView.js similarity index 100% rename from src/layout/ColorView.js rename to src/view-base/ColorView.js diff --git a/src/layout/HorizontalPanAndZoomView.js b/src/view-base/HorizontalPanAndZoomView.js similarity index 98% rename from src/layout/HorizontalPanAndZoomView.js rename to src/view-base/HorizontalPanAndZoomView.js index b6517af624689..5ed95ebcf84ef 100644 --- a/src/layout/HorizontalPanAndZoomView.js +++ b/src/view-base/HorizontalPanAndZoomView.js @@ -9,7 +9,7 @@ import type { WheelWithShiftInteraction, WheelWithControlInteraction, WheelWithMetaInteraction, -} from '../useCanvasInteraction'; +} from './useCanvasInteraction'; import type {Rect} from './geometry'; import {Surface} from './Surface'; @@ -19,7 +19,7 @@ import { MIN_ZOOM_LEVEL, MAX_ZOOM_LEVEL, MOVE_WHEEL_DELTA_THRESHOLD, -} from '../canvas/constants'; // TODO: Remove external dependency +} from './constants'; type HorizontalPanAndZoomState = $ReadOnly<{| /** Horizontal offset; positive in the left direction */ diff --git a/src/layout/ResizableSplitView.js b/src/view-base/ResizableSplitView.js similarity index 99% rename from src/layout/ResizableSplitView.js rename to src/view-base/ResizableSplitView.js index e06c5e4b8155f..b7c57a6ffb23a 100644 --- a/src/layout/ResizableSplitView.js +++ b/src/view-base/ResizableSplitView.js @@ -5,7 +5,7 @@ import type { MouseDownInteraction, MouseMoveInteraction, MouseUpInteraction, -} from '../useCanvasInteraction'; +} from './useCanvasInteraction'; import type {Rect, Size} from './geometry'; import nullthrows from 'nullthrows'; diff --git a/src/layout/Surface.js b/src/view-base/Surface.js similarity index 56% rename from src/layout/Surface.js rename to src/view-base/Surface.js index 52ed723e30442..eb5eec0bf5391 100644 --- a/src/layout/Surface.js +++ b/src/view-base/Surface.js @@ -1,13 +1,40 @@ // @flow -import type {Interaction} from '../useCanvasInteraction'; +import type {Interaction} from './useCanvasInteraction'; import type {Size} from './geometry'; -import {getCanvasContext} from '../canvas/canvasUtils'; +import memoize from 'memoize-one'; import {View} from './View'; import {zeroPoint} from './geometry'; +// hidpi canvas: https://www.html5rocks.com/en/tutorials/canvas/hidpi/ +function configureRetinaCanvas(canvas, height, width) { + const dpr: number = window.devicePixelRatio || 1; + canvas.width = width * dpr; + canvas.height = height * dpr; + canvas.style.width = `${width}px`; + canvas.style.height = `${height}px`; + return dpr; +} + +const getCanvasContext = memoize( + ( + canvas: HTMLCanvasElement, + height: number, + width: number, + scaleCanvas: boolean = true, + ): CanvasRenderingContext2D => { + const context = canvas.getContext('2d', {alpha: false}); + if (scaleCanvas) { + const dpr = configureRetinaCanvas(canvas, height, width); + // Scale all drawing operations by the dpr, so you don't have to worry about the difference. + context.scale(dpr, dpr); + } + return context; + }, +); + /** * Represents the canvas surface and a view heirarchy. A surface is also the * place where all interactions enter the view heirarchy. diff --git a/src/layout/VerticalScrollView.js b/src/view-base/VerticalScrollView.js similarity index 96% rename from src/layout/VerticalScrollView.js rename to src/view-base/VerticalScrollView.js index 4e72af1483164..2cbbb9cc1b8f6 100644 --- a/src/layout/VerticalScrollView.js +++ b/src/view-base/VerticalScrollView.js @@ -6,13 +6,13 @@ import type { MouseMoveInteraction, MouseUpInteraction, WheelPlainInteraction, -} from '../useCanvasInteraction'; +} from './useCanvasInteraction'; import type {Rect} from './geometry'; import {Surface} from './Surface'; import {View} from './View'; import {rectContainsPoint} from './geometry'; -import {MOVE_WHEEL_DELTA_THRESHOLD} from '../canvas/constants'; // TODO: Remove external dependency +import {MOVE_WHEEL_DELTA_THRESHOLD} from './constants'; type VerticalScrollState = $ReadOnly<{| offsetY: number, diff --git a/src/layout/View.js b/src/view-base/View.js similarity index 99% rename from src/layout/View.js rename to src/view-base/View.js index a8b42c7b68dde..4c14eb2730c02 100644 --- a/src/layout/View.js +++ b/src/view-base/View.js @@ -1,6 +1,6 @@ // @flow -import type {Interaction} from '../useCanvasInteraction'; +import type {Interaction} from './useCanvasInteraction'; import type {Rect, Size} from './geometry'; import type {Layouter} from './layouter'; diff --git a/src/layout/__tests__/geometry-test.js b/src/view-base/__tests__/geometry-test.js similarity index 100% rename from src/layout/__tests__/geometry-test.js rename to src/view-base/__tests__/geometry-test.js diff --git a/src/view-base/constants.js b/src/view-base/constants.js new file mode 100644 index 0000000000000..6dac770774cc5 --- /dev/null +++ b/src/view-base/constants.js @@ -0,0 +1,4 @@ +export const MOVE_WHEEL_DELTA_THRESHOLD = 1; +export const ZOOM_WHEEL_DELTA_THRESHOLD = 1; +export const MIN_ZOOM_LEVEL = 0.25; +export const MAX_ZOOM_LEVEL = 1000; diff --git a/src/layout/geometry.js b/src/view-base/geometry.js similarity index 100% rename from src/layout/geometry.js rename to src/view-base/geometry.js diff --git a/src/layout/index.js b/src/view-base/index.js similarity index 86% rename from src/layout/index.js rename to src/view-base/index.js index ee378e9749846..9006e34f5de74 100644 --- a/src/layout/index.js +++ b/src/view-base/index.js @@ -8,3 +8,4 @@ export * from './VerticalScrollView'; export * from './View'; export * from './geometry'; export * from './layouter'; +export * from './useCanvasInteraction'; diff --git a/src/layout/layouter.js b/src/view-base/layouter.js similarity index 100% rename from src/layout/layouter.js rename to src/view-base/layouter.js diff --git a/src/useCanvasInteraction.js b/src/view-base/useCanvasInteraction.js similarity index 96% rename from src/useCanvasInteraction.js rename to src/view-base/useCanvasInteraction.js index ac1af7a8afc14..7e624179403ea 100644 --- a/src/useCanvasInteraction.js +++ b/src/view-base/useCanvasInteraction.js @@ -1,10 +1,10 @@ // @flow -import type {Point} from './layout'; -import type {NormalizedWheelDelta} from './util/normalizeWheel'; +import type {NormalizedWheelDelta} from './utils/normalizeWheel'; +import type {Point} from './geometry'; import {useEffect} from 'react'; -import {normalizeWheel} from './util/normalizeWheel'; +import {normalizeWheel} from './utils/normalizeWheel'; export type MouseDownInteraction = {| type: 'mousedown', diff --git a/src/util/normalizeWheel.js b/src/view-base/utils/normalizeWheel.js similarity index 100% rename from src/util/normalizeWheel.js rename to src/view-base/utils/normalizeWheel.js From 09fbff453a23a0e694447ad695025947ebad382f Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Mon, 10 Aug 2020 09:24:32 +0800 Subject: [PATCH 078/116] Reimplement zoom to batch (#123) --- src/CanvasPage.js | 29 +++++++++++------------ src/view-base/HorizontalPanAndZoomView.js | 29 +++++++++++++++++++++++ 2 files changed, 43 insertions(+), 15 deletions(-) diff --git a/src/CanvasPage.js b/src/CanvasPage.js index 227797bf09223..a1256879e6fed 100644 --- a/src/CanvasPage.js +++ b/src/CanvasPage.js @@ -86,21 +86,10 @@ const copySummary = (data, measure) => { ); }; -// TODO: Migrate zoomToBatch to new views architecture -// const zoomToBatch = (data, measure, state) => { -// const {zoomTo} = state; -// if (!zoomTo) { -// return; -// } -// const {batchUID} = measure; -// const [startTime, stopTime] = getBatchRange(batchUID, data); -// zoomTo(startTime, stopTime); -// }; - const syncedHorizontalPanAndZoomViews: HorizontalPanAndZoomView[] = []; const syncAllHorizontalPanAndZoomViewStates: HorizontalPanAndZoomViewOnChangeCallback = ( newState, - view, + view?: HorizontalPanAndZoomView, ) => { syncedHorizontalPanAndZoomViews.forEach( syncedView => @@ -108,6 +97,16 @@ const syncAllHorizontalPanAndZoomViewStates: HorizontalPanAndZoomViewOnChangeCal ); }; +const zoomToBatch = (data, measure) => { + const {batchUID} = measure; + const [startTime, stopTime] = getBatchRange(batchUID, data); + syncedHorizontalPanAndZoomViews.forEach(syncedView => + // Using time as range works because the views' intrinsic content size is + // based on time. + syncedView.zoomToRange(startTime, stopTime), + ); +}; + type AutoSizedCanvasProps = {| data: ReactProfilerData, height: number, @@ -425,13 +424,13 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) { Copy component stack )} - {/* {measure !== null && ( + {measure !== null && ( zoomToBatch(contextData.data, measure, state)} + onClick={() => zoomToBatch(contextData.data, measure)} title="Zoom to batch"> Zoom to batch - )} */} + )} {measure !== null && ( copySummary(contextData.data, measure)} diff --git a/src/view-base/HorizontalPanAndZoomView.js b/src/view-base/HorizontalPanAndZoomView.js index 5ed95ebcf84ef..9eba0b280d711 100644 --- a/src/view-base/HorizontalPanAndZoomView.js +++ b/src/view-base/HorizontalPanAndZoomView.js @@ -152,6 +152,35 @@ export class HorizontalPanAndZoomView extends View { super.layoutSubviews(); } + /** + * Zoom to a specific range of the content specified as a range of the + * content view's intrinsic content size. + * + * Does not inform callbacks of state change since this is a public API. + */ + zoomToRange(startX: number, endX: number) { + // Zoom and offset must be done separately, so that if the zoom level is + // clamped the offset will still be correct (unless it gets clamped too). + const zoomClampedState = this._clampedProposedStateZoomLevel({ + ...this._panAndZoomState, + // Let: + // I = intrinsic content width, i = zoom range = (endX - startX). + // W = contentView's final zoomed width, w = this view's width + // Goal: we want the visible width w to only contain the requested range i. + // Derivation: + // (1) i/I = w/W (by intuitive definition of variables) + // (2) W = zoomLevel * I (definition of zoomLevel) + // => zoomLevel = W/I (algebraic manipulation) + // = w/i (rearranging (1)) + zoomLevel: this.frame.size.width / (endX - startX), + }); + const offsetAdjustedState = this._clampedProposedStateOffsetX({ + ...zoomClampedState, + offsetX: -startX * zoomClampedState.zoomLevel, + }); + this._setPanAndZoomState(offsetAdjustedState); + } + _handleMouseDown(interaction: MouseDownInteraction) { if (rectContainsPoint(interaction.payload.location, this.frame)) { this._isPanning = true; From d1b1b50b89bcba5fc399daf7ebfb01161cd47055 Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Mon, 10 Aug 2020 14:48:53 +0800 Subject: [PATCH 079/116] Fix tooltip (#121) * Minor clean up of EventTooltip.js * Fix root cause of #47 and improve tooltip styling Tooltips would go offscreen because of the way `top` is defined. This commit fixes that root cause by changing CanvasPage to position fixed so that tooltips will be positioned relative to the DOM rather than the CanvasPage div. Undoes some of the changes made in #78 as this commit fixes the root cause of the bug. * Disable component name truncation Although this was Brian's recommendation (see #67), I don't think component names will be very long because the source code for those will be really annoying. * Set mouse location on every interaction to fix #87 * Introduce 768-char component name length limit Covers the unlikely edge case that a component name is unreasonably long. --- src/CanvasPage.css | 1 - src/CanvasPage.js | 27 +++----- src/EventTooltip.css | 20 +++++- src/EventTooltip.js | 128 +++++++++++++++-------------------- src/utils/useSmartTooltip.js | 2 +- 5 files changed, 83 insertions(+), 95 deletions(-) diff --git a/src/CanvasPage.css b/src/CanvasPage.css index 0a22311f084dd..e5d238a0d9d2c 100644 --- a/src/CanvasPage.css +++ b/src/CanvasPage.css @@ -4,5 +4,4 @@ bottom: 0.5rem; left: 0.5rem; right: 0.5rem; - overflow: hidden; } diff --git a/src/CanvasPage.js b/src/CanvasPage.js index a1256879e6fed..bf2ff72f9323d 100644 --- a/src/CanvasPage.js +++ b/src/CanvasPage.js @@ -250,25 +250,19 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) { const interactor = useCallback( interaction => { - if ( - hoveredEvent && - (hoveredEvent.event || - hoveredEvent.measure || - hoveredEvent.flamechartStackFrame || - hoveredEvent.userTimingMark) - ) { - setMouseLocation({ - x: interaction.payload.event.x, - y: interaction.payload.event.y, - }); - } if (canvasRef.current === null) { return; } surfaceRef.current.handleInteraction(interaction); - surfaceRef.current.displayIfNeeded(); + // Defer drawing to canvas until React's commit phase, to avoid drawing + // twice and to ensure that both the canvas and DOM elements managed by + // React are in sync. + setMouseLocation({ + x: interaction.payload.event.x, + y: interaction.payload.event.y, + }); }, - [surfaceRef, hoveredEvent, setMouseLocation], + [surfaceRef, canvasRef, hoveredEvent, setMouseLocation], ); useCanvasInteraction(canvasRef, interactor); @@ -387,10 +381,7 @@ function AutoSizedCanvas({data, height, width}: AutoSizedCanvasProps) { hoveredEvent, ]); - // When React component renders, rerender surface. - // TODO: See if displaying on rAF would make more sense since we're somewhat - // decoupled from React and we don't want to render canvas multiple times per - // frame. + // Draw to canvas in React's commit phase useLayoutEffect(() => { surfaceRef.current.displayIfNeeded(); }); diff --git a/src/EventTooltip.css b/src/EventTooltip.css index f60e83208cc55..789736cb38308 100644 --- a/src/EventTooltip.css +++ b/src/EventTooltip.css @@ -1,5 +1,5 @@ .Tooltip { - position: absolute; + position: fixed; display: inline-block; border-radius: 0.125rem; max-width: 300px; @@ -31,12 +31,20 @@ } .DetailsGridURL { + word-break: break-all; + max-height: 50vh; overflow: hidden; } +.FlamechartStackFrameName { + word-break: break-word; + margin-left: 0.4rem; +} + .ComponentName { font-weight: bold; - word-wrap: break-word; + word-break: break-word; + margin-right: 0.4rem; } .ComponentStack { @@ -61,3 +69,11 @@ white-space: pre; --gradient-height: 5em; } + +.ReactMeasureLabel { + margin-left: 0.4rem; +} + +.UserTimingLabel { + word-break: break-word; +} diff --git a/src/EventTooltip.js b/src/EventTooltip.js index da94f3800e503..54c7d33327276 100644 --- a/src/EventTooltip.js +++ b/src/EventTooltip.js @@ -32,14 +32,14 @@ function formatDuration(ms) { return prettyMilliseconds(ms, {millisecondsDecimalDigits: 3}); } -function trimComponentName(name) { - if (name.length > 128) { - return name.substring(0, 127) + '...'; +function trimmedString(string: string, length: number): string { + if (string.length > length) { + return `${string.substr(0, length - 1)}…`; } - return name; + return string; } -function getReactEventLabel(type) { +function getReactEventLabel(type): string | null { switch (type) { case 'schedule-render': return 'render scheduled'; @@ -58,7 +58,25 @@ function getReactEventLabel(type) { } } -function getReactMeasureLabel(type: string) { +function getReactEventColor(event: ReactEvent): string | null { + switch (event.type) { + case 'schedule-render': + return COLORS.REACT_SCHEDULE_HOVER; + case 'schedule-state-update': + case 'schedule-force-update': + return event.isCascading + ? COLORS.REACT_SCHEDULE_CASCADING_HOVER + : COLORS.REACT_SCHEDULE_HOVER; + case 'suspense-suspend': + case 'suspense-resolved': + case 'suspense-rejected': + return COLORS.REACT_SUSPEND_HOVER; + default: + return null; + } +} + +function getReactMeasureLabel(type): string | null { switch (type) { case 'commit': return 'commit'; @@ -85,65 +103,18 @@ export default function EventTooltip({data, hoveredEvent, origin}: Props) { return null; } - const {event, flamechartStackFrame, measure, userTimingMark} = hoveredEvent; + const {event, measure, flamechartStackFrame, userTimingMark} = hoveredEvent; if (event !== null) { - switch (event.type) { - case 'schedule-render': - return ( - - ); - case 'schedule-state-update': // eslint-disable-line no-case-declarations - case 'schedule-force-update': - const color = event.isCascading - ? COLORS.REACT_SCHEDULE_CASCADING_HOVER - : COLORS.REACT_SCHEDULE_HOVER; - return ( - - ); - case 'suspense-suspend': - case 'suspense-resolved': - case 'suspense-rejected': - return ( - - ); - default: - console.warn(`Unexpected event type "${event.type}"`); - break; - } + return ; } else if (measure !== null) { - switch (measure.type) { - case 'commit': - case 'render-idle': - case 'render': - case 'layout-effects': - case 'passive-effects': - return ( - - ); - default: - console.warn(`Unexpected measure type "${measure.type}"`); - break; - } + return ( + + ); } else if (flamechartStackFrame !== null) { return ( - {formatDuration(duration)} {trimComponentName(name)} + {formatDuration(duration)} + {name}
Timestamp:
{formatTimestamp(timestamp)}
@@ -210,24 +182,28 @@ const TooltipFlamechartNode = ({ }; const TooltipReactEvent = ({ - color, event, tooltipRef, }: { - color: string, event: ReactEvent, tooltipRef: Return, }) => { - const {componentName, componentStack, timestamp, type} = event; - const label = getReactEventLabel(type); + const label = getReactEventLabel(event.type); + const color = getReactEventColor(event); + if (!label || !color) { + console.warn(`Unexpected event type "${event.type}"`); + return null; + } + + const {componentName, componentStack, timestamp} = event; return (
{componentName && ( - {trimComponentName(componentName)} + {trimmedString(componentName, 768)} - )}{' '} + )} {label}
@@ -255,13 +231,19 @@ const TooltipReactMeasure = ({ measure: ReactMeasure, tooltipRef: Return, }) => { - const {batchUID, duration, timestamp, type, lanes} = measure; - const label = getReactMeasureLabel(type); + const label = getReactMeasureLabel(measure.type); + if (!label) { + console.warn(`Unexpected measure type "${measure.type}"`); + return null; + } + + const {batchUID, duration, timestamp, lanes} = measure; const [startTime, stopTime] = getBatchRange(batchUID, data); return (
- {formatDuration(duration)} {label} + {formatDuration(duration)} + {label}
Timestamp:
@@ -287,7 +269,7 @@ const TooltipUserTimingMark = ({ const {name, timestamp} = mark; return (
- {name} + {name}
Timestamp:
diff --git a/src/utils/useSmartTooltip.js b/src/utils/useSmartTooltip.js index 652721f96d2ad..fede223a231ad 100644 --- a/src/utils/useSmartTooltip.js +++ b/src/utils/useSmartTooltip.js @@ -57,7 +57,7 @@ export default function useSmartTooltip({ element.style.left = `${mouseX + TOOLTIP_OFFSET}px`; } } - }); + }, [mouseX, mouseY, ref]); return ref; } From a530c70820623e5d1d9e79621e2bda8865bd385f Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Mon, 10 Aug 2020 20:54:47 +0800 Subject: [PATCH 080/116] Switch to concurrent React (#122) --- package.json | 4 ++-- src/index.js | 5 ++--- yarn.lock | 27 +++++++++++++++++++++------ 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index 1f5b96791b83b..a42b1652869e8 100644 --- a/package.json +++ b/package.json @@ -19,8 +19,8 @@ "memoize-one": "^5.1.1", "nullthrows": "^1.1.1", "pretty-ms": "^7.0.0", - "react": "^16.13.1", - "react-dom": "^16.13.1", + "react": "experimental", + "react-dom": "experimental", "react-virtualized-auto-sizer": "^1.0.2", "scheduler": "^0.19.1" }, diff --git a/src/index.js b/src/index.js index 4eea703ec3e2c..118fd8b71cc6f 100644 --- a/src/index.js +++ b/src/index.js @@ -1,13 +1,12 @@ import React from 'react'; -import {render} from 'react-dom'; +import {unstable_createRoot as createRoot} from 'react-dom'; import App from './App'; import './index.css'; const container = document.getElementById('root'); -render( +createRoot(container).render( , - container, ); diff --git a/yarn.lock b/yarn.lock index 6a99e751157bb..a2a4a6c1af935 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8984,15 +8984,14 @@ randomfill@^1.0.3: randombytes "^2.0.5" safe-buffer "^5.1.0" -react-dom@^16.13.1: - version "16.13.1" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.13.1.tgz#c1bd37331a0486c078ee54c4740720993b2e0e7f" - integrity sha512-81PIMmVLnCNLO/fFOQxdQkvEq/+Hfpv24XNJfpyZhTRfO0QcmQIF/PgCa1zCOj2w1hrn12MFLyaJ/G0+Mxtfag== +react-dom@experimental: + version "0.0.0-experimental-3d0895557" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-0.0.0-experimental-3d0895557.tgz#8fdb08f45c461fa38fbc8a4b458450abcd10910b" + integrity sha512-rb88BTYlEfDbZ+1TlRKGDUflKGJWptlXKUv+4jI+LM91mr6idkWGf+3U92m7hb09aYvlHozt7slrGV3P5XuFGg== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" - prop-types "^15.6.2" - scheduler "^0.19.1" + scheduler "0.0.0-experimental-3d0895557" react-is@^16.12.0: version "16.13.1" @@ -9032,6 +9031,14 @@ react@^16.7.0: object-assign "^4.1.1" prop-types "^15.6.2" +react@experimental: + version "0.0.0-experimental-3d0895557" + resolved "https://registry.yarnpkg.com/react/-/react-0.0.0-experimental-3d0895557.tgz#0c6c95681bf93e023f74a5448f2261ba99b41c01" + integrity sha512-/5nwNTI6QypTthi9rRbf74i/ac6UTf3syRrgJpkzV52470aNlF+Qq6D6e7kFiPpcfh3A/V6vnMCPtmB/rNnElA== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + read-pkg-up@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" @@ -9488,6 +9495,14 @@ saxes@^5.0.0: dependencies: xmlchars "^2.2.0" +scheduler@0.0.0-experimental-3d0895557: + version "0.0.0-experimental-3d0895557" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.0.0-experimental-3d0895557.tgz#ad5e191e8f13d4b61e52d3fce0a6a42a769eacd7" + integrity sha512-6ZRZa9aolgD+1y2w/vagSzXeoAMllKNBgrVLWdlP2uAHYRsmOQaAkOedqrtEFnqDg/k0SI+uvUhYe5BWOtzFkQ== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + scheduler@^0.19.1: version "0.19.1" resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.19.1.tgz#4f3e2ed2c1a7d65681f4c854fa8c5a1ccb40f196" From 82ff1b31191bde931df674fd4812489d9db354d2 Mon Sep 17 00:00:00 2001 From: Kartik Choudhary Date: Fri, 14 Aug 2020 04:39:20 +0000 Subject: [PATCH 081/116] Update color palette for accessibility (#126) --- src/content-views/constants.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/content-views/constants.js b/src/content-views/constants.js index 1dd70c02611de..03f8b49bbc9c9 100644 --- a/src/content-views/constants.js +++ b/src/content-views/constants.js @@ -38,27 +38,27 @@ export const COLORS = Object.freeze({ PRIORITY_BACKGROUND: '#ededf0', PRIORITY_BORDER: '#d7d7db', PRIORITY_LABEL: '#272727', - USER_TIMING: '#45a1ff', - USER_TIMING_HOVER: '#0a84ff', + USER_TIMING: '#c9cacd', + USER_TIMING_HOVER: '#93959a', REACT_IDLE: '#edf6ff', REACT_IDLE_SELECTED: '#EDF6FF', REACT_IDLE_HOVER: '#EDF6FF', REACT_RENDER: '#9fc3f3', REACT_RENDER_SELECTED: '#64A9F5', - REACT_RENDER_HOVER: '#298ff6', + REACT_RENDER_HOVER: '#2683E2', REACT_COMMIT: '#ff718e', REACT_COMMIT_SELECTED: '#FF5277', - REACT_COMMIT_HOVER: '#ff335f', - REACT_LAYOUT_EFFECTS: '#c49edd', + REACT_COMMIT_HOVER: '#ed0030', + REACT_LAYOUT_EFFECTS: '#c88ff0', REACT_LAYOUT_EFFECTS_SELECTED: '#934FC1', - REACT_LAYOUT_EFFECTS_HOVER: '#6200a4', - REACT_PASSIVE_EFFECTS: '#c49edd', + REACT_LAYOUT_EFFECTS_HOVER: '#601593', + REACT_PASSIVE_EFFECTS: '#c88ff0', REACT_PASSIVE_EFFECTS_SELECTED: '#934FC1', - REACT_PASSIVE_EFFECTS_HOVER: '#6200a4', + REACT_PASSIVE_EFFECTS_HOVER: '#601593', REACT_SCHEDULE: '#9fc3f3', - REACT_SCHEDULE_HOVER: '#298ff6', + REACT_SCHEDULE_HOVER: '#2683E2', REACT_SCHEDULE_CASCADING: '#ff718e', - REACT_SCHEDULE_CASCADING_HOVER: '#ff335f', + REACT_SCHEDULE_CASCADING_HOVER: '#ed0030', REACT_SUSPEND: '#a6e59f', REACT_SUSPEND_HOVER: '#13bc00', REACT_WORK_BORDER: '#ffffff', From 6c8320828db10088c0950f7e142855338108878a Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Mon, 17 Aug 2020 16:45:20 +0800 Subject: [PATCH 082/116] [Import Prep][1/n] Upgrade dependencies (#128) Test Plan === 1. `yarn lint` 1. `yarn flow`: Speedscope no longer has any errors (Flow type generation fixed in updated Speedscope fork). Works towards #38 1. `yarn test` 1. `yarn start` --- package.json | 18 +- yarn.lock | 757 ++++++++++++++++++++++++++------------------------- 2 files changed, 391 insertions(+), 384 deletions(-) diff --git a/package.json b/package.json index a42b1652869e8..7b6e72bd9ee51 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "author": "Brian Vaughn ", "license": "MIT", "dependencies": { - "@elg/speedscope": "1.9.0-846c4e7", + "@elg/speedscope": "1.9.0-c46bbab", "array-binsearch": "^1.0.1", "clipboard-js": "^0.3.6", "d3-hierarchy": "^1.1.9", @@ -19,20 +19,20 @@ "memoize-one": "^5.1.1", "nullthrows": "^1.1.1", "pretty-ms": "^7.0.0", - "react": "experimental", - "react-dom": "experimental", + "react": "^0.0.0-experimental-94c0244ba", + "react-dom": "^0.0.0-experimental-94c0244ba", "react-virtualized-auto-sizer": "^1.0.2", "scheduler": "^0.19.1" }, "devDependencies": { "@babel/core": "^7.11.1", - "@testing-library/jest-dom": "^5.11.2", + "@testing-library/jest-dom": "^5.11.3", "@testing-library/react": "^10.4.8", "babel-eslint": "^10.1.0", - "babel-jest": "^26.2.2", + "babel-jest": "^26.3.0", "babel-preset-react-app": "^9.1.2", "confusing-browser-globals": "^1.0.9", - "eslint": "^7.6.0", + "eslint": "^7.7.0", "eslint-config-fbjs": "^1.1.1", "eslint-config-prettier": "^6.11.0", "eslint-plugin-babel": "^5.3.1", @@ -40,10 +40,10 @@ "eslint-plugin-jest": "^23.20.0", "eslint-plugin-no-for-of-loops": "^1.0.1", "eslint-plugin-prettier": "^3.1.4", - "eslint-plugin-react": "^7.20.5", - "flow-bin": "^0.130.0", + "eslint-plugin-react": "^7.20.6", + "flow-bin": "^0.131.0", "identity-obj-proxy": "^3.0.0", - "jest": "^26.2.2", + "jest": "^26.4.0", "parcel": "2.0.0-beta.1", "postcss-modules": "^3.2.0", "prettier": "1.19.1" diff --git a/yarn.lock b/yarn.lock index a2a4a6c1af935..a5ee75b46ee17 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2578,10 +2578,10 @@ exec-sh "^0.3.2" minimist "^1.2.0" -"@elg/speedscope@1.9.0-846c4e7": - version "1.9.0-846c4e7" - resolved "https://registry.yarnpkg.com/@elg/speedscope/-/speedscope-1.9.0-846c4e7.tgz#6f31b6055717f10b67dfa032c8b64bc1e6aab881" - integrity sha512-OyXdOG/kAJLbR2/UIEZDqdKpcQ1FAa/Q/vQr1Pnx+4QoqN4gM5H4eqY4MFs3VbQykjmna7SpJ6D0pldWp3641A== +"@elg/speedscope@1.9.0-c46bbab": + version "1.9.0-c46bbab" + resolved "https://registry.yarnpkg.com/@elg/speedscope/-/speedscope-1.9.0-c46bbab.tgz#c11bfb533b5363e366b368b7f9ce6239a96c5fb6" + integrity sha512-qW38AOykb7OeeNVUECxw3jRZanKaPdm5h0iC6sYadBkYJtxjM/TK+Mlu1WJZJu9wfgQLlZiA9siGYRwJwXdJTw== dependencies: opn "5.3.0" react "^16.13.1" @@ -2607,93 +2607,93 @@ resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd" integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw== -"@jest/console@^26.2.0": - version "26.2.0" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-26.2.0.tgz#d18f2659b90930e7ec3925fb7209f1ba2cf463f0" - integrity sha512-mXQfx3nSLwiHm1i7jbu+uvi+vvpVjNGzIQYLCfsat9rapC+MJkS4zBseNrgJE0vU921b3P67bQzhduphjY3Tig== +"@jest/console@^26.3.0": + version "26.3.0" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-26.3.0.tgz#ed04063efb280c88ba87388b6f16427c0a85c856" + integrity sha512-/5Pn6sJev0nPUcAdpJHMVIsA8sKizL2ZkcKPE5+dJrCccks7tcM7c9wbgHudBJbxXLoTbqsHkG1Dofoem4F09w== dependencies: - "@jest/types" "^26.2.0" + "@jest/types" "^26.3.0" "@types/node" "*" chalk "^4.0.0" - jest-message-util "^26.2.0" - jest-util "^26.2.0" + jest-message-util "^26.3.0" + jest-util "^26.3.0" slash "^3.0.0" -"@jest/core@^26.2.2": - version "26.2.2" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-26.2.2.tgz#63de01ffce967618003dd7a0164b05c8041b81a9" - integrity sha512-UwA8gNI8aeV4FHGfGAUfO/DHjrFVvlBravF1Tm9Kt6qFE+6YHR47kFhgdepOFpADEKstyO+MVdPvkV6/dyt9sA== +"@jest/core@^26.4.0": + version "26.4.0" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-26.4.0.tgz#8f42ae45640b46b4f8ffee134dcd408c210ab1ef" + integrity sha512-mpXm4OjWQbz7qbzGIiSqvfNZ1FxX6ywWgLtdSD2luPORt5zKPtqcdDnX7L8RdfMaj1znDBgN2+gB094ZIr7vnA== dependencies: - "@jest/console" "^26.2.0" - "@jest/reporters" "^26.2.2" - "@jest/test-result" "^26.2.0" - "@jest/transform" "^26.2.2" - "@jest/types" "^26.2.0" + "@jest/console" "^26.3.0" + "@jest/reporters" "^26.4.0" + "@jest/test-result" "^26.3.0" + "@jest/transform" "^26.3.0" + "@jest/types" "^26.3.0" "@types/node" "*" ansi-escapes "^4.2.1" chalk "^4.0.0" exit "^0.1.2" graceful-fs "^4.2.4" - jest-changed-files "^26.2.0" - jest-config "^26.2.2" - jest-haste-map "^26.2.2" - jest-message-util "^26.2.0" + jest-changed-files "^26.3.0" + jest-config "^26.4.0" + jest-haste-map "^26.3.0" + jest-message-util "^26.3.0" jest-regex-util "^26.0.0" - jest-resolve "^26.2.2" - jest-resolve-dependencies "^26.2.2" - jest-runner "^26.2.2" - jest-runtime "^26.2.2" - jest-snapshot "^26.2.2" - jest-util "^26.2.0" - jest-validate "^26.2.0" - jest-watcher "^26.2.0" + jest-resolve "^26.4.0" + jest-resolve-dependencies "^26.4.0" + jest-runner "^26.4.0" + jest-runtime "^26.4.0" + jest-snapshot "^26.4.0" + jest-util "^26.3.0" + jest-validate "^26.4.0" + jest-watcher "^26.3.0" micromatch "^4.0.2" p-each-series "^2.1.0" rimraf "^3.0.0" slash "^3.0.0" strip-ansi "^6.0.0" -"@jest/environment@^26.2.0": - version "26.2.0" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-26.2.0.tgz#f6faee1630fcc2fad208953164bccb31dbe0e45f" - integrity sha512-oCgp9NmEiJ5rbq9VI/v/yYLDpladAAVvFxZgNsnJxOETuzPZ0ZcKKHYjKYwCtPOP1WCrM5nmyuOhMStXFGHn+g== +"@jest/environment@^26.3.0": + version "26.3.0" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-26.3.0.tgz#e6953ab711ae3e44754a025f838bde1a7fd236a0" + integrity sha512-EW+MFEo0DGHahf83RAaiqQx688qpXgl99wdb8Fy67ybyzHwR1a58LHcO376xQJHfmoXTu89M09dH3J509cx2AA== dependencies: - "@jest/fake-timers" "^26.2.0" - "@jest/types" "^26.2.0" + "@jest/fake-timers" "^26.3.0" + "@jest/types" "^26.3.0" "@types/node" "*" - jest-mock "^26.2.0" + jest-mock "^26.3.0" -"@jest/fake-timers@^26.2.0": - version "26.2.0" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-26.2.0.tgz#b485c57dc4c74d61406a339807a9af4bac74b75a" - integrity sha512-45Gfe7YzYTKqTayBrEdAF0qYyAsNRBzfkV0IyVUm3cx7AsCWlnjilBM4T40w7IXT5VspOgMPikQlV0M6gHwy/g== +"@jest/fake-timers@^26.3.0": + version "26.3.0" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-26.3.0.tgz#f515d4667a6770f60ae06ae050f4e001126c666a" + integrity sha512-ZL9ytUiRwVP8ujfRepffokBvD2KbxbqMhrXSBhSdAhISCw3gOkuntisiSFv+A6HN0n0fF4cxzICEKZENLmW+1A== dependencies: - "@jest/types" "^26.2.0" + "@jest/types" "^26.3.0" "@sinonjs/fake-timers" "^6.0.1" "@types/node" "*" - jest-message-util "^26.2.0" - jest-mock "^26.2.0" - jest-util "^26.2.0" + jest-message-util "^26.3.0" + jest-mock "^26.3.0" + jest-util "^26.3.0" -"@jest/globals@^26.2.0": - version "26.2.0" - resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-26.2.0.tgz#ad78f1104f250c1a4bf5184a2ba51facc59b23f6" - integrity sha512-Hoc6ScEIPaym7RNytIL2ILSUWIGKlwEv+JNFof9dGYOdvPjb2evEURSslvCMkNuNg1ECEClTE8PH7ULlMJntYA== +"@jest/globals@^26.4.0": + version "26.4.0" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-26.4.0.tgz#ebab3ba937a200a4b3805f2e552bdf869465ffea" + integrity sha512-QKwoVAeL9d0xaEM9ebPvfc+bolN04F+o3zM2jswGDBiiNjCogZ3LvOaqumRdDyz6kLmbx+UhgMBAVuLunbXZ2A== dependencies: - "@jest/environment" "^26.2.0" - "@jest/types" "^26.2.0" - expect "^26.2.0" + "@jest/environment" "^26.3.0" + "@jest/types" "^26.3.0" + expect "^26.4.0" -"@jest/reporters@^26.2.2": - version "26.2.2" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-26.2.2.tgz#5a8632ab410f4fc57782bc05dcf115e91818e869" - integrity sha512-7854GPbdFTAorWVh+RNHyPO9waRIN6TcvCezKVxI1khvFq9YjINTW7J3WU+tbR038Ynn6WjYred6vtT0YmIWVQ== +"@jest/reporters@^26.4.0": + version "26.4.0" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-26.4.0.tgz#dd3f03979170dd25dc6a9b746c693b591056d753" + integrity sha512-14OPAAuYhgRBSNxAocVluX6ksdMdK/EuP9NmtBXU9g1uKaVBrPnohn/CVm6iMot1a9iU8BCxa5715YRf8FEg/A== dependencies: "@bcoe/v8-coverage" "^0.2.3" - "@jest/console" "^26.2.0" - "@jest/test-result" "^26.2.0" - "@jest/transform" "^26.2.2" - "@jest/types" "^26.2.0" + "@jest/console" "^26.3.0" + "@jest/test-result" "^26.3.0" + "@jest/transform" "^26.3.0" + "@jest/types" "^26.3.0" chalk "^4.0.0" collect-v8-coverage "^1.0.0" exit "^0.1.2" @@ -2704,63 +2704,63 @@ istanbul-lib-report "^3.0.0" istanbul-lib-source-maps "^4.0.0" istanbul-reports "^3.0.2" - jest-haste-map "^26.2.2" - jest-resolve "^26.2.2" - jest-util "^26.2.0" - jest-worker "^26.2.1" + jest-haste-map "^26.3.0" + jest-resolve "^26.4.0" + jest-util "^26.3.0" + jest-worker "^26.3.0" slash "^3.0.0" source-map "^0.6.0" string-length "^4.0.1" terminal-link "^2.0.0" - v8-to-istanbul "^4.1.3" + v8-to-istanbul "^5.0.1" optionalDependencies: node-notifier "^7.0.0" -"@jest/source-map@^26.1.0": - version "26.1.0" - resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-26.1.0.tgz#a6a020d00e7d9478f4b690167c5e8b77e63adb26" - integrity sha512-XYRPYx4eEVX15cMT9mstnO7hkHP3krNtKfxUYd8L7gbtia8JvZZ6bMzSwa6IQJENbudTwKMw5R1BePRD+bkEmA== +"@jest/source-map@^26.3.0": + version "26.3.0" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-26.3.0.tgz#0e646e519883c14c551f7b5ae4ff5f1bfe4fc3d9" + integrity sha512-hWX5IHmMDWe1kyrKl7IhFwqOuAreIwHhbe44+XH2ZRHjrKIh0LO5eLQ/vxHFeAfRwJapmxuqlGAEYLadDq6ZGQ== dependencies: callsites "^3.0.0" graceful-fs "^4.2.4" source-map "^0.6.0" -"@jest/test-result@^26.2.0": - version "26.2.0" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-26.2.0.tgz#51c9b165c8851cfcf7a3466019114785e154f76b" - integrity sha512-kgPlmcVafpmfyQEu36HClK+CWI6wIaAWDHNxfQtGuKsgoa2uQAYdlxjMDBEa3CvI40+2U3v36gQF6oZBkoKatw== +"@jest/test-result@^26.3.0": + version "26.3.0" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-26.3.0.tgz#46cde01fa10c0aaeb7431bf71e4a20d885bc7fdb" + integrity sha512-a8rbLqzW/q7HWheFVMtghXV79Xk+GWwOK1FrtimpI5n1la2SY0qHri3/b0/1F0Ve0/yJmV8pEhxDfVwiUBGtgg== dependencies: - "@jest/console" "^26.2.0" - "@jest/types" "^26.2.0" + "@jest/console" "^26.3.0" + "@jest/types" "^26.3.0" "@types/istanbul-lib-coverage" "^2.0.0" collect-v8-coverage "^1.0.0" -"@jest/test-sequencer@^26.2.2": - version "26.2.2" - resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-26.2.2.tgz#5e8091f2e6c61fdf242af566cb820a4eadc6c4af" - integrity sha512-SliZWon5LNqV/lVXkeowSU6L8++FGOu3f43T01L1Gv6wnFDP00ER0utV9jyK9dVNdXqfMNCN66sfcyar/o7BNw== +"@jest/test-sequencer@^26.4.0": + version "26.4.0" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-26.4.0.tgz#f4902772392d478d310dd6fd3b6818fb4bcc4c82" + integrity sha512-9Z7lCShS7vERp+DRwIVNH/6sHMWwJK1DPnGCpGeVLGJJWJ4Y08sQI3vIKdmKHu2KmwlUBpRM+BFf7NlVUkl5XA== dependencies: - "@jest/test-result" "^26.2.0" + "@jest/test-result" "^26.3.0" graceful-fs "^4.2.4" - jest-haste-map "^26.2.2" - jest-runner "^26.2.2" - jest-runtime "^26.2.2" + jest-haste-map "^26.3.0" + jest-runner "^26.4.0" + jest-runtime "^26.4.0" -"@jest/transform@^26.2.2": - version "26.2.2" - resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-26.2.2.tgz#86c005c8d5d749ac54d8df53ea58675fffe7a97e" - integrity sha512-c1snhvi5wRVre1XyoO3Eef5SEWpuBCH/cEbntBUd9tI5sNYiBDmO0My/lc5IuuGYKp/HFIHV1eZpSx5yjdkhKw== +"@jest/transform@^26.3.0": + version "26.3.0" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-26.3.0.tgz#c393e0e01459da8a8bfc6d2a7c2ece1a13e8ba55" + integrity sha512-Isj6NB68QorGoFWvcOjlUhpkT56PqNIsXKR7XfvoDlCANn/IANlh8DrKAA2l2JKC3yWSMH5wS0GwuQM20w3b2A== dependencies: "@babel/core" "^7.1.0" - "@jest/types" "^26.2.0" + "@jest/types" "^26.3.0" babel-plugin-istanbul "^6.0.0" chalk "^4.0.0" convert-source-map "^1.4.0" fast-json-stable-stringify "^2.0.0" graceful-fs "^4.2.4" - jest-haste-map "^26.2.2" + jest-haste-map "^26.3.0" jest-regex-util "^26.0.0" - jest-util "^26.2.0" + jest-util "^26.3.0" micromatch "^4.0.2" pirates "^4.0.1" slash "^3.0.0" @@ -2777,13 +2777,13 @@ "@types/yargs" "^15.0.0" chalk "^3.0.0" -"@jest/types@^26.2.0": - version "26.2.0" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.2.0.tgz#b28ca1fb517a4eb48c0addea7fcd9edc4ab45721" - integrity sha512-lvm3rJvctxd7+wxKSxxbzpDbr4FXDLaC57WEKdUIZ2cjTYuxYSc0zlyD7Z4Uqr5VdKxRUrtwIkiqBuvgf8uKJA== +"@jest/types@^26.3.0": + version "26.3.0" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.3.0.tgz#97627bf4bdb72c55346eef98e3b3f7ddc4941f71" + integrity sha512-BDPG23U0qDeAvU4f99haztXwdAg3hz4El95LkAM+tHAqqhiVzRpEGHHU8EDxT/AnxOrA65YjLBwDahdJ9pTLJQ== dependencies: "@types/istanbul-lib-coverage" "^2.0.0" - "@types/istanbul-reports" "^1.1.1" + "@types/istanbul-reports" "^3.0.0" "@types/node" "*" "@types/yargs" "^15.0.0" chalk "^4.0.0" @@ -3584,10 +3584,10 @@ dom-accessibility-api "^0.4.5" pretty-format "^25.5.0" -"@testing-library/jest-dom@^5.11.2": - version "5.11.2" - resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.11.2.tgz#c49de331555c70127b5d7fc97344ad5265f4c54c" - integrity sha512-s+rWJx+lanEGKqvOl4qJR0rGjCrxsEjj9qjxFlg4NV4/FRD7fnUUAWPHqwpyafNHfLYArs58FADgdn4UKmjFmw== +"@testing-library/jest-dom@^5.11.3": + version "5.11.3" + resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.11.3.tgz#3802cb244e9ab50559a20344698a2d41f9bf11ec" + integrity sha512-vP8ABJt4+YIzu9UItbpJ6nM5zN3g9/tpLcp2DJiXyfX9gnwgcmLsa42+YiohNGEtSUTsseb6xB9HAwlgk8WdaQ== dependencies: "@babel/runtime" "^7.9.2" "@types/testing-library__jest-dom" "^5.9.1" @@ -3678,6 +3678,13 @@ "@types/istanbul-lib-coverage" "*" "@types/istanbul-lib-report" "*" +"@types/istanbul-reports@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.0.tgz#508b13aa344fa4976234e75dddcc34925737d821" + integrity sha512-nwKNbvnwJ2/mndE9ItP/zc2TCzw6uuodnF4EHYWD+gCQDVBuRQL5UzbZD0/ezy1iKsFU2ZQiDqg4M9dN4+wZgA== + dependencies: + "@types/istanbul-lib-report" "*" + "@types/jest@*": version "26.0.0" resolved "https://registry.yarnpkg.com/@types/jest/-/jest-26.0.0.tgz#a6d7573dffa9c68cbbdf38f2e0de26f159e11134" @@ -4085,16 +4092,16 @@ babel-eslint@^10.1.0: eslint-visitor-keys "^1.0.0" resolve "^1.12.0" -babel-jest@^26.2.2: - version "26.2.2" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-26.2.2.tgz#70f618f2d7016ed71b232241199308985462f812" - integrity sha512-JmLuePHgA+DSOdOL8lPxCgD2LhPPm+rdw1vnxR73PpIrnmKCS2/aBhtkAcxQWuUcW2hBrH8MJ3LKXE7aWpNZyA== +babel-jest@^26.3.0: + version "26.3.0" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-26.3.0.tgz#10d0ca4b529ca3e7d1417855ef7d7bd6fc0c3463" + integrity sha512-sxPnQGEyHAOPF8NcUsD0g7hDCnvLL2XyblRBcgrzTWBB/mAIpWow3n1bEL+VghnnZfreLhFSBsFluRoK2tRK4g== dependencies: - "@jest/transform" "^26.2.2" - "@jest/types" "^26.2.0" + "@jest/transform" "^26.3.0" + "@jest/types" "^26.3.0" "@types/babel__core" "^7.1.7" babel-plugin-istanbul "^6.0.0" - babel-preset-jest "^26.2.0" + babel-preset-jest "^26.3.0" chalk "^4.0.0" graceful-fs "^4.2.4" slash "^3.0.0" @@ -4148,7 +4155,7 @@ babel-plugin-transform-react-remove-prop-types@0.4.24: resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz#f2edaf9b4c6a5fbe5c1d678bfb531078c1555f3a" integrity sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA== -babel-preset-current-node-syntax@^0.1.2: +babel-preset-current-node-syntax@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-0.1.3.tgz#b4b547acddbf963cba555ba9f9cbbb70bfd044da" integrity sha512-uyexu1sVwcdFnyq9o8UQYsXwXflIh8LvrF5+cKrYam93ned1CStffB3+BEcsxGSgagoA3GEyjDqO4a/58hyPYQ== @@ -4165,13 +4172,13 @@ babel-preset-current-node-syntax@^0.1.2: "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" "@babel/plugin-syntax-optional-chaining" "^7.8.3" -babel-preset-jest@^26.2.0: - version "26.2.0" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-26.2.0.tgz#f198201a4e543a43eb40bc481e19736e095fd3e0" - integrity sha512-R1k8kdP3R9phYQugXeNnK/nvCGlBzG4m3EoIIukC80GXb6wCv2XiwPhK6K9MAkQcMszWBYvl2Wm+yigyXFQqXg== +babel-preset-jest@^26.3.0: + version "26.3.0" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-26.3.0.tgz#ed6344506225c065fd8a0b53e191986f74890776" + integrity sha512-5WPdf7nyYi2/eRxCbVrE1kKCWxgWY4RsPEbdJWFm7QsesFGqjdkyLeu1zRkwM1cxK6EPIlNd6d2AxLk7J+t4pw== dependencies: babel-plugin-jest-hoist "^26.2.0" - babel-preset-current-node-syntax "^0.1.2" + babel-preset-current-node-syntax "^0.1.3" babel-preset-react-app@^9.1.2: version "9.1.2" @@ -5199,10 +5206,10 @@ diff-sequences@^25.2.6: resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-25.2.6.tgz#5f467c00edd35352b7bca46d7927d60e687a76dd" integrity sha512-Hq8o7+6GaZeoFjtpgvRBUknSXNeJiCx7V9Fr94ZMljNiCr9n9L8H8aJqgWOQiDDGdyn29fRNcDdRVJ5fdyihfg== -diff-sequences@^26.0.0: - version "26.0.0" - resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-26.0.0.tgz#0760059a5c287637b842bd7085311db7060e88a6" - integrity sha512-JC/eHYEC3aSS0vZGjuoc4vHA0yAQTzhQQldXMeMF+JlxLGJlCO38Gma82NV9gk1jGFz8mDzUMeaKXvjRRdJ2dg== +diff-sequences@^26.3.0: + version "26.3.0" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-26.3.0.tgz#62a59b1b29ab7fd27cef2a33ae52abe73042d0a2" + integrity sha512-5j5vdRcw3CNctePNYN0Wy2e/JbWT6cAYnXv5OuqPhDpyCGc0uLu2TK0zOCJWNB9kOIfYMSpIulRaDgIi4HJ6Ig== diffie-hellman@^5.0.0: version "5.0.3" @@ -5540,10 +5547,10 @@ eslint-plugin-prettier@^3.1.4: dependencies: prettier-linter-helpers "^1.0.0" -eslint-plugin-react@^7.20.5: - version "7.20.5" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.20.5.tgz#29480f3071f64a04b2c3d99d9b460ce0f76fb857" - integrity sha512-ajbJfHuFnpVNJjhyrfq+pH1C0gLc2y94OiCbAXT5O0J0YCKaFEHDV8+3+mDOr+w8WguRX+vSs1bM2BDG0VLvCw== +eslint-plugin-react@^7.20.6: + version "7.20.6" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.20.6.tgz#4d7845311a93c463493ccfa0a19c9c5d0fd69f60" + integrity sha512-kidMTE5HAEBSLu23CUDvj8dc3LdBU0ri1scwHBZjI41oDv4tjsWZKU7MQccFzH1QYPYhsnTF2ovh7JlcIcmxgg== dependencies: array-includes "^3.1.1" array.prototype.flatmap "^1.2.3" @@ -5582,10 +5589,10 @@ eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3 resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== -eslint@^7.6.0: - version "7.6.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.6.0.tgz#522d67cfaea09724d96949c70e7a0550614d64d6" - integrity sha512-QlAManNtqr7sozWm5TF4wIH9gmUm2hE3vNRUvyoYAa4y1l5/jxD/PQStEjBMQtCqZmSep8UxrcecI60hOpe61w== +eslint@^7.7.0: + version "7.7.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.7.0.tgz#18beba51411927c4b64da0a8ceadefe4030d6073" + integrity sha512-1KUxLzos0ZVsyL81PnRN335nDtQ8/vZUD6uMtWbF+5zDtjKcsklIi78XoE0MVL93QvWTu+E5y44VyyCsOMBrIg== dependencies: "@babel/code-frame" "^7.0.0" ajv "^6.10.0" @@ -5756,16 +5763,16 @@ expand-brackets@^2.1.4: snapdragon "^0.8.1" to-regex "^3.0.1" -expect@^26.2.0: - version "26.2.0" - resolved "https://registry.yarnpkg.com/expect/-/expect-26.2.0.tgz#0140dd9cc7376d7833852e9cda88c05414f1efba" - integrity sha512-8AMBQ9UVcoUXt0B7v+5/U5H6yiUR87L6eKCfjE3spx7Ya5lF+ebUo37MCFBML2OiLfkX1sxmQOZhIDonyVTkcw== +expect@^26.4.0: + version "26.4.0" + resolved "https://registry.yarnpkg.com/expect/-/expect-26.4.0.tgz#34a0aae523343b0931ff1cf0aa972dfe40edfab4" + integrity sha512-dbYDJhFcqQsamlos6nEwAMe+ahdckJBk5fmw1DYGLQGabGSlUuT+Fm2jHYw5119zG3uIhP+lCQbjJhFEdZMJtg== dependencies: - "@jest/types" "^26.2.0" + "@jest/types" "^26.3.0" ansi-styles "^4.0.0" - jest-get-type "^26.0.0" - jest-matcher-utils "^26.2.0" - jest-message-util "^26.2.0" + jest-get-type "^26.3.0" + jest-matcher-utils "^26.4.0" + jest-message-util "^26.3.0" jest-regex-util "^26.0.0" extend-shallow@^2.0.1: @@ -5959,10 +5966,10 @@ flatted@^2.0.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== -flow-bin@^0.130.0: - version "0.130.0" - resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.130.0.tgz#e25eaf891af96da371ff6a9fa99d709f24ce9252" - integrity sha512-1TSLwCPXvKPwiae7Fh+dpipCzwlHQ1UcBHfCpQImz+hsxYIUWkLWJWEm34bY6I7dSM4ekSiVeP02BhzVJGwtpw== +flow-bin@^0.131.0: + version "0.131.0" + resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.131.0.tgz#d4228b6070afdf3b2a76acdee77a7f3f8e8f5133" + integrity sha512-fZmoIBcDrtLhy/NNMxwJysSYzMr1ksRcAOMi3AHSoYXfcuQqTvhGJx+wqjlIOqIwz8RRYm8J4V4JrSJbIKP+Xg== follow-redirects@^1.0.0: version "1.9.0" @@ -6853,57 +6860,57 @@ istanbul-reports@^3.0.2: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" -jest-changed-files@^26.2.0: - version "26.2.0" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-26.2.0.tgz#b4946201defe0c919a2f3d601e9f98cb21dacc15" - integrity sha512-+RyJb+F1K/XBLIYiL449vo5D+CvlHv29QveJUWNPXuUicyZcq+tf1wNxmmFeRvAU1+TzhwqczSjxnCCFt7+8iA== +jest-changed-files@^26.3.0: + version "26.3.0" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-26.3.0.tgz#68fb2a7eb125f50839dab1f5a17db3607fe195b1" + integrity sha512-1C4R4nijgPltX6fugKxM4oQ18zimS7LqQ+zTTY8lMCMFPrxqBFb7KJH0Z2fRQJvw2Slbaipsqq7s1mgX5Iot+g== dependencies: - "@jest/types" "^26.2.0" + "@jest/types" "^26.3.0" execa "^4.0.0" throat "^5.0.0" -jest-cli@^26.2.2: - version "26.2.2" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-26.2.2.tgz#4c273e5474baafac1eb15fd25aaafb4703f5ffbc" - integrity sha512-vVcly0n/ijZvdy6gPQiQt0YANwX2hLTPQZHtW7Vi3gcFdKTtif7YpI85F8R8JYy5DFSWz4x1OW0arnxlziu5Lw== +jest-cli@^26.4.0: + version "26.4.0" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-26.4.0.tgz#9cbd6be818cd818d85bafe2cffa1dbf043602b28" + integrity sha512-kw2Pr3V2x9/WzSDGsbz/MJBNlCoPMxMudrIavft4bqRlv5tASjU51tyO+1Os1LdW2dAnLQZYsxFUZ8oWPyssGQ== dependencies: - "@jest/core" "^26.2.2" - "@jest/test-result" "^26.2.0" - "@jest/types" "^26.2.0" + "@jest/core" "^26.4.0" + "@jest/test-result" "^26.3.0" + "@jest/types" "^26.3.0" chalk "^4.0.0" exit "^0.1.2" graceful-fs "^4.2.4" import-local "^3.0.2" is-ci "^2.0.0" - jest-config "^26.2.2" - jest-util "^26.2.0" - jest-validate "^26.2.0" + jest-config "^26.4.0" + jest-util "^26.3.0" + jest-validate "^26.4.0" prompts "^2.0.1" yargs "^15.3.1" -jest-config@^26.2.2: - version "26.2.2" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-26.2.2.tgz#f3ebc7e2bc3f49de8ed3f8007152f345bb111917" - integrity sha512-2lhxH0y4YFOijMJ65usuf78m7+9/8+hAb1PZQtdRdgnQpAb4zP6KcVDDktpHEkspBKnc2lmFu+RQdHukUUbiTg== +jest-config@^26.4.0: + version "26.4.0" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-26.4.0.tgz#72ff3d0418b7ee7fdd9e2bcaef4dec10b38b3b02" + integrity sha512-MxsvrBug8YY+C4QcUBtmgnHyFeW7w3Ouk/w9eplCDN8VJGVyBEZFe8Lxzfp2pSqh0Dqurqv8Oik2YkbekGUlxg== dependencies: "@babel/core" "^7.1.0" - "@jest/test-sequencer" "^26.2.2" - "@jest/types" "^26.2.0" - babel-jest "^26.2.2" + "@jest/test-sequencer" "^26.4.0" + "@jest/types" "^26.3.0" + babel-jest "^26.3.0" chalk "^4.0.0" deepmerge "^4.2.2" glob "^7.1.1" graceful-fs "^4.2.4" - jest-environment-jsdom "^26.2.0" - jest-environment-node "^26.2.0" - jest-get-type "^26.0.0" - jest-jasmine2 "^26.2.2" + jest-environment-jsdom "^26.3.0" + jest-environment-node "^26.3.0" + jest-get-type "^26.3.0" + jest-jasmine2 "^26.4.0" jest-regex-util "^26.0.0" - jest-resolve "^26.2.2" - jest-util "^26.2.0" - jest-validate "^26.2.0" + jest-resolve "^26.4.0" + jest-util "^26.3.0" + jest-validate "^26.4.0" micromatch "^4.0.2" - pretty-format "^26.2.0" + pretty-format "^26.4.0" jest-diff@^25.1.0, jest-diff@^25.2.1, jest-diff@^25.5.0: version "25.5.0" @@ -6915,15 +6922,15 @@ jest-diff@^25.1.0, jest-diff@^25.2.1, jest-diff@^25.5.0: jest-get-type "^25.2.6" pretty-format "^25.5.0" -jest-diff@^26.2.0: - version "26.2.0" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-26.2.0.tgz#dee62c771adbb23ae585f3f1bd289a6e8ef4f298" - integrity sha512-Wu4Aopi2nzCsHWLBlD48TgRy3Z7OsxlwvHNd1YSnHc7q1NJfrmyCPoUXrTIrydQOG5ApaYpsAsdfnMbJqV1/wQ== +jest-diff@^26.4.0: + version "26.4.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-26.4.0.tgz#d073a0a11952b5bd9f1ff39bb9ad24304a0c55f7" + integrity sha512-wwC38HlOW+iTq6j5tkj/ZamHn6/nrdcEOc/fKaVILNtN2NLWGdkfRaHWwfNYr5ehaLvuoG2LfCZIcWByVj0gjg== dependencies: chalk "^4.0.0" - diff-sequences "^26.0.0" - jest-get-type "^26.0.0" - pretty-format "^26.2.0" + diff-sequences "^26.3.0" + jest-get-type "^26.3.0" + pretty-format "^26.4.0" jest-docblock@^26.0.0: version "26.0.0" @@ -6932,104 +6939,104 @@ jest-docblock@^26.0.0: dependencies: detect-newline "^3.0.0" -jest-each@^26.2.0: - version "26.2.0" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-26.2.0.tgz#aec8efa01d072d7982c900e74940863385fa884e" - integrity sha512-gHPCaho1twWHB5bpcfnozlc6mrMi+VAewVPNgmwf81x2Gzr6XO4dl+eOrwPWxbkYlgjgrYjWK2xgKnixbzH3Ew== +jest-each@^26.4.0: + version "26.4.0" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-26.4.0.tgz#c53605b20e7a0a58d6dcf4d8b2f309e607d35d5a" + integrity sha512-+cyBh1ehs6thVT/bsZVG+WwmRn2ix4Q4noS9yLZgM10yGWPW12/TDvwuOV2VZXn1gi09/ZwJKJWql6YW1C9zNw== dependencies: - "@jest/types" "^26.2.0" + "@jest/types" "^26.3.0" chalk "^4.0.0" - jest-get-type "^26.0.0" - jest-util "^26.2.0" - pretty-format "^26.2.0" - -jest-environment-jsdom@^26.2.0: - version "26.2.0" - resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-26.2.0.tgz#6443a6f3569297dcaa4371dddf93acaf167302dc" - integrity sha512-sDG24+5M4NuIGzkI3rJW8XUlrpkvIdE9Zz4jhD8OBnVxAw+Y1jUk9X+lAOD48nlfUTlnt3lbAI3k2Ox+WF3S0g== - dependencies: - "@jest/environment" "^26.2.0" - "@jest/fake-timers" "^26.2.0" - "@jest/types" "^26.2.0" + jest-get-type "^26.3.0" + jest-util "^26.3.0" + pretty-format "^26.4.0" + +jest-environment-jsdom@^26.3.0: + version "26.3.0" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-26.3.0.tgz#3b749ba0f3a78e92ba2c9ce519e16e5dd515220c" + integrity sha512-zra8He2btIMJkAzvLaiZ9QwEPGEetbxqmjEBQwhH3CA+Hhhu0jSiEJxnJMbX28TGUvPLxBt/zyaTLrOPF4yMJA== + dependencies: + "@jest/environment" "^26.3.0" + "@jest/fake-timers" "^26.3.0" + "@jest/types" "^26.3.0" "@types/node" "*" - jest-mock "^26.2.0" - jest-util "^26.2.0" + jest-mock "^26.3.0" + jest-util "^26.3.0" jsdom "^16.2.2" -jest-environment-node@^26.2.0: - version "26.2.0" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-26.2.0.tgz#fee89e06bdd4bed3f75ee2978d73ede9bb57a681" - integrity sha512-4M5ExTYkJ19efBzkiXtBi74JqKLDciEk4CEsp5tTjWGYMrlKFQFtwIVG3tW1OGE0AlXhZjuHPwubuRYY4j4uOw== +jest-environment-node@^26.3.0: + version "26.3.0" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-26.3.0.tgz#56c6cfb506d1597f94ee8d717072bda7228df849" + integrity sha512-c9BvYoo+FGcMj5FunbBgtBnbR5qk3uky8PKyRVpSfe2/8+LrNQMiXX53z6q2kY+j15SkjQCOSL/6LHnCPLVHNw== dependencies: - "@jest/environment" "^26.2.0" - "@jest/fake-timers" "^26.2.0" - "@jest/types" "^26.2.0" + "@jest/environment" "^26.3.0" + "@jest/fake-timers" "^26.3.0" + "@jest/types" "^26.3.0" "@types/node" "*" - jest-mock "^26.2.0" - jest-util "^26.2.0" + jest-mock "^26.3.0" + jest-util "^26.3.0" jest-get-type@^25.2.6: version "25.2.6" resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-25.2.6.tgz#0b0a32fab8908b44d508be81681487dbabb8d877" integrity sha512-DxjtyzOHjObRM+sM1knti6or+eOgcGU4xVSb2HNP1TqO4ahsT+rqZg+nyqHWJSvWgKC5cG3QjGFBqxLghiF/Ig== -jest-get-type@^26.0.0: - version "26.0.0" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-26.0.0.tgz#381e986a718998dbfafcd5ec05934be538db4039" - integrity sha512-zRc1OAPnnws1EVfykXOj19zo2EMw5Hi6HLbFCSjpuJiXtOWAYIjNsHVSbpQ8bDX7L5BGYGI8m+HmKdjHYFF0kg== +jest-get-type@^26.3.0: + version "26.3.0" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-26.3.0.tgz#e97dc3c3f53c2b406ca7afaed4493b1d099199e0" + integrity sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig== -jest-haste-map@^26.2.2: - version "26.2.2" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-26.2.2.tgz#6d4267b1903854bfdf6a871419f35a82f03ae71e" - integrity sha512-3sJlMSt+NHnzCB+0KhJ1Ut4zKJBiJOlbrqEYNdRQGlXTv8kqzZWjUKQRY3pkjmlf+7rYjAV++MQ4D6g4DhAyOg== +jest-haste-map@^26.3.0: + version "26.3.0" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-26.3.0.tgz#c51a3b40100d53ab777bfdad382d2e7a00e5c726" + integrity sha512-DHWBpTJgJhLLGwE5Z1ZaqLTYqeODQIZpby0zMBsCU9iRFHYyhklYqP4EiG73j5dkbaAdSZhgB938mL51Q5LeZA== dependencies: - "@jest/types" "^26.2.0" + "@jest/types" "^26.3.0" "@types/graceful-fs" "^4.1.2" "@types/node" "*" anymatch "^3.0.3" fb-watchman "^2.0.0" graceful-fs "^4.2.4" jest-regex-util "^26.0.0" - jest-serializer "^26.2.0" - jest-util "^26.2.0" - jest-worker "^26.2.1" + jest-serializer "^26.3.0" + jest-util "^26.3.0" + jest-worker "^26.3.0" micromatch "^4.0.2" sane "^4.0.3" walker "^1.0.7" optionalDependencies: fsevents "^2.1.2" -jest-jasmine2@^26.2.2: - version "26.2.2" - resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-26.2.2.tgz#d82b1721fac2b153a4f8b3f0c95e81e702812de2" - integrity sha512-Q8AAHpbiZMVMy4Hz9j1j1bg2yUmPa1W9StBvcHqRaKa9PHaDUMwds8LwaDyzP/2fkybcTQE4+pTMDOG9826tEw== +jest-jasmine2@^26.4.0: + version "26.4.0" + resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-26.4.0.tgz#f66b2237203df4227d3bdbb4b8a0de54ba877d35" + integrity sha512-cGBxwzDDKB09EPJ4pE69BMDv+2lO442IB1xQd+vL3cua2OKdeXQK6iDlQKoRX/iP0RgU5T8sn9yahLcx/+ox8Q== dependencies: "@babel/traverse" "^7.1.0" - "@jest/environment" "^26.2.0" - "@jest/source-map" "^26.1.0" - "@jest/test-result" "^26.2.0" - "@jest/types" "^26.2.0" + "@jest/environment" "^26.3.0" + "@jest/source-map" "^26.3.0" + "@jest/test-result" "^26.3.0" + "@jest/types" "^26.3.0" "@types/node" "*" chalk "^4.0.0" co "^4.6.0" - expect "^26.2.0" + expect "^26.4.0" is-generator-fn "^2.0.0" - jest-each "^26.2.0" - jest-matcher-utils "^26.2.0" - jest-message-util "^26.2.0" - jest-runtime "^26.2.2" - jest-snapshot "^26.2.2" - jest-util "^26.2.0" - pretty-format "^26.2.0" + jest-each "^26.4.0" + jest-matcher-utils "^26.4.0" + jest-message-util "^26.3.0" + jest-runtime "^26.4.0" + jest-snapshot "^26.4.0" + jest-util "^26.3.0" + pretty-format "^26.4.0" throat "^5.0.0" -jest-leak-detector@^26.2.0: - version "26.2.0" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-26.2.0.tgz#073ee6d8db7a9af043e7ce99d8eea17a4fb0cc50" - integrity sha512-aQdzTX1YiufkXA1teXZu5xXOJgy7wZQw6OJ0iH5CtQlOETe6gTSocaYKUNui1SzQ91xmqEUZ/WRavg9FD82rtQ== +jest-leak-detector@^26.4.0: + version "26.4.0" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-26.4.0.tgz#1efeeef693af3c9332062876add5ac5f25cb0a70" + integrity sha512-7EXKKEKnAWUPyiVtGZzJflbPOtYUdlNoevNVOkAcPpdR8xWiYKPGNGA6sz25S+8YhZq3rmkQJYAh3/P0VnoRwA== dependencies: - jest-get-type "^26.0.0" - pretty-format "^26.2.0" + jest-get-type "^26.3.0" + pretty-format "^26.4.0" jest-matcher-utils@^25.1.0: version "25.5.0" @@ -7041,23 +7048,23 @@ jest-matcher-utils@^25.1.0: jest-get-type "^25.2.6" pretty-format "^25.5.0" -jest-matcher-utils@^26.2.0: - version "26.2.0" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-26.2.0.tgz#b107af98c2b8c557ffd46c1adf06f794aa52d622" - integrity sha512-2cf/LW2VFb3ayPHrH36ZDjp9+CAeAe/pWBAwsV8t3dKcrINzXPVxq8qMWOxwt5BaeBCx4ZupVGH7VIgB8v66vQ== +jest-matcher-utils@^26.4.0: + version "26.4.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-26.4.0.tgz#2bce9a939e008b894faf1bd4b5bb58facd00c252" + integrity sha512-u+xdCdq+F262DH+PutJKXLGr2H5P3DImdJCir51PGSfi3TtbLQ5tbzKaN8BkXbiTIU6ayuAYBWTlU1nyckVdzA== dependencies: chalk "^4.0.0" - jest-diff "^26.2.0" - jest-get-type "^26.0.0" - pretty-format "^26.2.0" + jest-diff "^26.4.0" + jest-get-type "^26.3.0" + pretty-format "^26.4.0" -jest-message-util@^26.2.0: - version "26.2.0" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-26.2.0.tgz#757fbc1323992297092bb9016a71a2eb12fd22ea" - integrity sha512-g362RhZaJuqeqG108n1sthz5vNpzTNy926eNDszo4ncRbmmcMRIUAZibnd6s5v2XSBCChAxQtCoN25gnzp7JbQ== +jest-message-util@^26.3.0: + version "26.3.0" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-26.3.0.tgz#3bdb538af27bb417f2d4d16557606fd082d5841a" + integrity sha512-xIavRYqr4/otGOiLxLZGj3ieMmjcNE73Ui+LdSW/Y790j5acqCsAdDiLIbzHCZMpN07JOENRWX5DcU+OQ+TjTA== dependencies: "@babel/code-frame" "^7.0.0" - "@jest/types" "^26.2.0" + "@jest/types" "^26.3.0" "@types/stack-utils" "^1.0.1" chalk "^4.0.0" graceful-fs "^4.2.4" @@ -7065,12 +7072,12 @@ jest-message-util@^26.2.0: slash "^3.0.0" stack-utils "^2.0.2" -jest-mock@^26.2.0: - version "26.2.0" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-26.2.0.tgz#a1b3303ab38c34aa1dbbc16ab57cdc1a59ed50d1" - integrity sha512-XeC7yWtWmWByoyVOHSsE7NYsbXJLtJNgmhD7z4MKumKm6ET0si81bsSLbQ64L5saK3TgsHo2B/UqG5KNZ1Sp/Q== +jest-mock@^26.3.0: + version "26.3.0" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-26.3.0.tgz#ee62207c3c5ebe5f35b760e1267fee19a1cfdeba" + integrity sha512-PeaRrg8Dc6mnS35gOo/CbZovoDPKAeB1FICZiuagAgGvbWdNNyjQjkOaGUa/3N3JtpQ/Mh9P4A2D4Fv51NnP8Q== dependencies: - "@jest/types" "^26.2.0" + "@jest/types" "^26.3.0" "@types/node" "*" jest-pnp-resolver@^1.2.2: @@ -7083,170 +7090,170 @@ jest-regex-util@^26.0.0: resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-26.0.0.tgz#d25e7184b36e39fd466c3bc41be0971e821fee28" integrity sha512-Gv3ZIs/nA48/Zvjrl34bf+oD76JHiGDUxNOVgUjh3j890sblXryjY4rss71fPtD/njchl6PSE2hIhvyWa1eT0A== -jest-resolve-dependencies@^26.2.2: - version "26.2.2" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-26.2.2.tgz#2ad3cd9281730e9a5c487cd846984c5324e47929" - integrity sha512-S5vufDmVbQXnpP7435gr710xeBGUFcKNpNswke7RmFvDQtmqPjPVU/rCeMlEU0p6vfpnjhwMYeaVjKZAy5QYJA== +jest-resolve-dependencies@^26.4.0: + version "26.4.0" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-26.4.0.tgz#c911fc991e1ae034dd8d01c192f23459d66b87b7" + integrity sha512-hznK/hlrlhu8hwdbieRdHFKmcV83GW8t30libt/v6j1L3IEzb8iN21SaWzV8KRAAK4ijiU0kuge0wnHn+0rytQ== dependencies: - "@jest/types" "^26.2.0" + "@jest/types" "^26.3.0" jest-regex-util "^26.0.0" - jest-snapshot "^26.2.2" + jest-snapshot "^26.4.0" -jest-resolve@^26.2.2: - version "26.2.2" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-26.2.2.tgz#324a20a516148d61bffa0058ed0c77c510ecfd3e" - integrity sha512-ye9Tj/ILn/0OgFPE/3dGpQPUqt4dHwIocxt5qSBkyzxQD8PbL0bVxBogX2FHxsd3zJA7V2H/cHXnBnNyyT9YoQ== +jest-resolve@^26.4.0: + version "26.4.0" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-26.4.0.tgz#6dc0af7fb93e65b73fec0368ca2b76f3eb59a6d7" + integrity sha512-bn/JoZTEXRSlEx3+SfgZcJAVuTMOksYq9xe9O6s4Ekg84aKBObEaVXKOEilULRqviSLAYJldnoWV9c07kwtiCg== dependencies: - "@jest/types" "^26.2.0" + "@jest/types" "^26.3.0" chalk "^4.0.0" graceful-fs "^4.2.4" jest-pnp-resolver "^1.2.2" - jest-util "^26.2.0" + jest-util "^26.3.0" read-pkg-up "^7.0.1" resolve "^1.17.0" slash "^3.0.0" -jest-runner@^26.2.2: - version "26.2.2" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-26.2.2.tgz#6d03d057886e9c782e10b2cf37443f902fe0e39e" - integrity sha512-/qb6ptgX+KQ+aNMohJf1We695kaAfuu3u3ouh66TWfhTpLd9WbqcF6163d/tMoEY8GqPztXPLuyG0rHRVDLxCA== +jest-runner@^26.4.0: + version "26.4.0" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-26.4.0.tgz#4cb91b266390fbf266294a7d8250d0e7bf8c7a9d" + integrity sha512-XF+tnUGolnPriu6Gg+HHWftspMjD5NkTV2mQppQnpZe39GcUangJ0al7aBGtA3GbVAcRd048DQiJPmsQRdugjw== dependencies: - "@jest/console" "^26.2.0" - "@jest/environment" "^26.2.0" - "@jest/test-result" "^26.2.0" - "@jest/types" "^26.2.0" + "@jest/console" "^26.3.0" + "@jest/environment" "^26.3.0" + "@jest/test-result" "^26.3.0" + "@jest/types" "^26.3.0" "@types/node" "*" chalk "^4.0.0" emittery "^0.7.1" exit "^0.1.2" graceful-fs "^4.2.4" - jest-config "^26.2.2" + jest-config "^26.4.0" jest-docblock "^26.0.0" - jest-haste-map "^26.2.2" - jest-leak-detector "^26.2.0" - jest-message-util "^26.2.0" - jest-resolve "^26.2.2" - jest-runtime "^26.2.2" - jest-util "^26.2.0" - jest-worker "^26.2.1" + jest-haste-map "^26.3.0" + jest-leak-detector "^26.4.0" + jest-message-util "^26.3.0" + jest-resolve "^26.4.0" + jest-runtime "^26.4.0" + jest-util "^26.3.0" + jest-worker "^26.3.0" source-map-support "^0.5.6" throat "^5.0.0" -jest-runtime@^26.2.2: - version "26.2.2" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-26.2.2.tgz#2480ff79320680a643031dd21998d7c63d83ab68" - integrity sha512-a8VXM3DxCDnCIdl9+QucWFfQ28KdqmyVFqeKLigHdErtsx56O2ZIdQkhFSuP1XtVrG9nTNHbKxjh5XL1UaFDVQ== - dependencies: - "@jest/console" "^26.2.0" - "@jest/environment" "^26.2.0" - "@jest/fake-timers" "^26.2.0" - "@jest/globals" "^26.2.0" - "@jest/source-map" "^26.1.0" - "@jest/test-result" "^26.2.0" - "@jest/transform" "^26.2.2" - "@jest/types" "^26.2.0" +jest-runtime@^26.4.0: + version "26.4.0" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-26.4.0.tgz#0b860f2bcf4f6047919c5b3fe74ed6adbe0056b4" + integrity sha512-1fjZgGpkyQBUTo59Vi19I4IcsBwzY6uwVFNjUmR06iIi3XRErkY28yimi4IUDRrofQErqcDEw2n3DF9WmQ6vEg== + dependencies: + "@jest/console" "^26.3.0" + "@jest/environment" "^26.3.0" + "@jest/fake-timers" "^26.3.0" + "@jest/globals" "^26.4.0" + "@jest/source-map" "^26.3.0" + "@jest/test-result" "^26.3.0" + "@jest/transform" "^26.3.0" + "@jest/types" "^26.3.0" "@types/yargs" "^15.0.0" chalk "^4.0.0" collect-v8-coverage "^1.0.0" exit "^0.1.2" glob "^7.1.3" graceful-fs "^4.2.4" - jest-config "^26.2.2" - jest-haste-map "^26.2.2" - jest-message-util "^26.2.0" - jest-mock "^26.2.0" + jest-config "^26.4.0" + jest-haste-map "^26.3.0" + jest-message-util "^26.3.0" + jest-mock "^26.3.0" jest-regex-util "^26.0.0" - jest-resolve "^26.2.2" - jest-snapshot "^26.2.2" - jest-util "^26.2.0" - jest-validate "^26.2.0" + jest-resolve "^26.4.0" + jest-snapshot "^26.4.0" + jest-util "^26.3.0" + jest-validate "^26.4.0" slash "^3.0.0" strip-bom "^4.0.0" yargs "^15.3.1" -jest-serializer@^26.2.0: - version "26.2.0" - resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-26.2.0.tgz#92dcae5666322410f4bf50211dd749274959ddac" - integrity sha512-V7snZI9IVmyJEu0Qy0inmuXgnMWDtrsbV2p9CRAcmlmPVwpC2ZM8wXyYpiugDQnwLHx0V4+Pnog9Exb3UO8M6Q== +jest-serializer@^26.3.0: + version "26.3.0" + resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-26.3.0.tgz#1c9d5e1b74d6e5f7e7f9627080fa205d976c33ef" + integrity sha512-IDRBQBLPlKa4flg77fqg0n/pH87tcRKwe8zxOVTWISxGpPHYkRZ1dXKyh04JOja7gppc60+soKVZ791mruVdow== dependencies: "@types/node" "*" graceful-fs "^4.2.4" -jest-snapshot@^26.2.2: - version "26.2.2" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-26.2.2.tgz#9d2eda083a4a1017b157e351868749bd63211799" - integrity sha512-NdjD8aJS7ePu268Wy/n/aR1TUisG0BOY+QOW4f6h46UHEKOgYmmkvJhh2BqdVZQ0BHSxTMt04WpCf9njzx8KtA== +jest-snapshot@^26.4.0: + version "26.4.0" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-26.4.0.tgz#efd42eef09bcb33e9a3eb98e229f2368c73c9235" + integrity sha512-vFGmNGWHMBomrlOpheTMoqihymovuH3GqfmaEIWoPpsxUXyxT3IlbxI5I4m2vg0uv3HUJYg5JoGrkgMzVsAwCg== dependencies: "@babel/types" "^7.0.0" - "@jest/types" "^26.2.0" + "@jest/types" "^26.3.0" "@types/prettier" "^2.0.0" chalk "^4.0.0" - expect "^26.2.0" + expect "^26.4.0" graceful-fs "^4.2.4" - jest-diff "^26.2.0" - jest-get-type "^26.0.0" - jest-haste-map "^26.2.2" - jest-matcher-utils "^26.2.0" - jest-message-util "^26.2.0" - jest-resolve "^26.2.2" + jest-diff "^26.4.0" + jest-get-type "^26.3.0" + jest-haste-map "^26.3.0" + jest-matcher-utils "^26.4.0" + jest-message-util "^26.3.0" + jest-resolve "^26.4.0" natural-compare "^1.4.0" - pretty-format "^26.2.0" + pretty-format "^26.4.0" semver "^7.3.2" -jest-util@^26.2.0: - version "26.2.0" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-26.2.0.tgz#0597d2a27c559340957609f106c408c17c1d88ac" - integrity sha512-YmDwJxLZ1kFxpxPfhSJ0rIkiZOM0PQbRcfH0TzJOhqCisCAsI1WcmoQqO83My9xeVA2k4n+rzg2UuexVKzPpig== +jest-util@^26.3.0: + version "26.3.0" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-26.3.0.tgz#a8974b191df30e2bf523ebbfdbaeb8efca535b3e" + integrity sha512-4zpn6bwV0+AMFN0IYhH/wnzIQzRaYVrz1A8sYnRnj4UXDXbOVtWmlaZkO9mipFqZ13okIfN87aDoJWB7VH6hcw== dependencies: - "@jest/types" "^26.2.0" + "@jest/types" "^26.3.0" "@types/node" "*" chalk "^4.0.0" graceful-fs "^4.2.4" is-ci "^2.0.0" micromatch "^4.0.2" -jest-validate@^26.2.0: - version "26.2.0" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-26.2.0.tgz#97fedf3e7984b7608854cbf925b9ca6ebcbdb78a" - integrity sha512-8XKn3hM6VIVmLNuyzYLCPsRCT83o8jMZYhbieh4dAyKLc4Ypr36rVKC+c8WMpWkfHHpGnEkvWUjjIAyobEIY/Q== +jest-validate@^26.4.0: + version "26.4.0" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-26.4.0.tgz#3874a7cc9e27328afac88899ee9e2fae5e3a4293" + integrity sha512-t56Z/FRMrLP6mpmje7/YgHy0wOzcuc6i3LBXz6kjmsUWYN62OuMdC86Vg9/dX59SvyitSqqegOrx+h7BkNXeaQ== dependencies: - "@jest/types" "^26.2.0" + "@jest/types" "^26.3.0" camelcase "^6.0.0" chalk "^4.0.0" - jest-get-type "^26.0.0" + jest-get-type "^26.3.0" leven "^3.1.0" - pretty-format "^26.2.0" + pretty-format "^26.4.0" -jest-watcher@^26.2.0: - version "26.2.0" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-26.2.0.tgz#45bdf2fecadd19c0a501f3b071a474dca636825b" - integrity sha512-674Boco4Joe0CzgKPL6K4Z9LgyLx+ZvW2GilbpYb8rFEUkmDGgsZdv1Hv5rxsRpb1HLgKUOL/JfbttRCuFdZXQ== +jest-watcher@^26.3.0: + version "26.3.0" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-26.3.0.tgz#f8ef3068ddb8af160ef868400318dc4a898eed08" + integrity sha512-XnLdKmyCGJ3VoF6G/p5ohbJ04q/vv5aH9ENI+i6BL0uu9WWB6Z7Z2lhQQk0d2AVZcRGp1yW+/TsoToMhBFPRdQ== dependencies: - "@jest/test-result" "^26.2.0" - "@jest/types" "^26.2.0" + "@jest/test-result" "^26.3.0" + "@jest/types" "^26.3.0" "@types/node" "*" ansi-escapes "^4.2.1" chalk "^4.0.0" - jest-util "^26.2.0" + jest-util "^26.3.0" string-length "^4.0.1" -jest-worker@^26.2.1: - version "26.2.1" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.2.1.tgz#5d630ab93f666b53f911615bc13e662b382bd513" - integrity sha512-+XcGMMJDTeEGncRb5M5Zq9P7K4sQ1sirhjdOxsN1462h6lFo9w59bl2LVQmdGEEeU3m+maZCkS2Tcc9SfCHO4A== +jest-worker@^26.3.0: + version "26.3.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.3.0.tgz#7c8a97e4f4364b4f05ed8bca8ca0c24de091871f" + integrity sha512-Vmpn2F6IASefL+DVBhPzI2J9/GJUsqzomdeN+P+dK8/jKxbh8R3BtFnx3FIta7wYlPU62cpJMJQo4kuOowcMnw== dependencies: "@types/node" "*" merge-stream "^2.0.0" supports-color "^7.0.0" -jest@^26.2.2: - version "26.2.2" - resolved "https://registry.yarnpkg.com/jest/-/jest-26.2.2.tgz#a022303887b145147204c5f66e6a5c832333c7e7" - integrity sha512-EkJNyHiAG1+A8pqSz7cXttoVa34hOEzN/MrnJhYnfp5VHxflVcf2pu3oJSrhiy6LfIutLdWo+n6q63tjcoIeig== +jest@^26.4.0: + version "26.4.0" + resolved "https://registry.yarnpkg.com/jest/-/jest-26.4.0.tgz#495e81dcff40f8a656e567c664af87b29c5c5922" + integrity sha512-lNCOS+ckRHE1wFyVtQClBmbsOVuH2GWUTJMDL3vunp9DXcah+V8vfvVVApngClcdoc3rgZpqOfCNKLjxjj2l4g== dependencies: - "@jest/core" "^26.2.2" + "@jest/core" "^26.4.0" import-local "^3.0.2" - jest-cli "^26.2.2" + jest-cli "^26.4.0" js-levenshtein@^1.1.3, js-levenshtein@^1.1.6: version "1.1.6" @@ -8845,12 +8852,12 @@ pretty-format@^25.2.1, pretty-format@^25.5.0: ansi-styles "^4.0.0" react-is "^16.12.0" -pretty-format@^26.2.0: - version "26.2.0" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.2.0.tgz#83ecc8d7de676ff224225055e72bd64821cec4f1" - integrity sha512-qi/8IuBu2clY9G7qCXgCdD1Bf9w+sXakdHTRToknzMtVy0g7c4MBWaZy7MfB7ndKZovRO6XRwJiAYqq+MC7SDA== +pretty-format@^26.4.0: + version "26.4.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.4.0.tgz#c08073f531429e9e5024049446f42ecc9f933a3b" + integrity sha512-mEEwwpCseqrUtuMbrJG4b824877pM5xald3AkilJ47Po2YLr97/siejYQHqj2oDQBeJNbu+Q0qUuekJ8F0NAPg== dependencies: - "@jest/types" "^26.2.0" + "@jest/types" "^26.3.0" ansi-regex "^5.0.0" ansi-styles "^4.0.0" react-is "^16.12.0" @@ -8984,14 +8991,14 @@ randomfill@^1.0.3: randombytes "^2.0.5" safe-buffer "^5.1.0" -react-dom@experimental: - version "0.0.0-experimental-3d0895557" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-0.0.0-experimental-3d0895557.tgz#8fdb08f45c461fa38fbc8a4b458450abcd10910b" - integrity sha512-rb88BTYlEfDbZ+1TlRKGDUflKGJWptlXKUv+4jI+LM91mr6idkWGf+3U92m7hb09aYvlHozt7slrGV3P5XuFGg== +react-dom@^0.0.0-experimental-94c0244ba: + version "0.0.0-experimental-94c0244ba" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-0.0.0-experimental-94c0244ba.tgz#1e715ca62608458058b99303d562ce77d3e699d8" + integrity sha512-rvyWGIxrtjImQaeo3/27ORpU5i7fTzPlQH/xkEI/wlLfuJ2zi7Tideln8y9xM2BA5mYA74sH103bMbIQbPWtGQ== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" - scheduler "0.0.0-experimental-3d0895557" + scheduler "0.0.0-experimental-94c0244ba" react-is@^16.12.0: version "16.13.1" @@ -9013,6 +9020,14 @@ react-virtualized-auto-sizer@^1.0.2: resolved "https://registry.yarnpkg.com/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.2.tgz#a61dd4f756458bbf63bd895a92379f9b70f803bd" integrity sha512-MYXhTY1BZpdJFjUovvYHVBmkq79szK/k7V3MO+36gJkWGkrXKtyr4vCPtpphaTLRAdDNoYEYFZWE8LjN+PIHNg== +react@^0.0.0-experimental-94c0244ba: + version "0.0.0-experimental-94c0244ba" + resolved "https://registry.yarnpkg.com/react/-/react-0.0.0-experimental-94c0244ba.tgz#eb63ece3eadcf231845b6ec9c4a8c1829ddcc1fe" + integrity sha512-67fLM+CA1w96JM0Ju5dv9lE3q1qSxVAi1iAOOyhXddhQJfs85bAJNM+gEMPBKbrhbhJGyHL1mLh1xqpOzokQ4w== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + react@^16.13.1: version "16.13.1" resolved "https://registry.yarnpkg.com/react/-/react-16.13.1.tgz#2e818822f1a9743122c063d6410d85c1e3afe48e" @@ -9031,14 +9046,6 @@ react@^16.7.0: object-assign "^4.1.1" prop-types "^15.6.2" -react@experimental: - version "0.0.0-experimental-3d0895557" - resolved "https://registry.yarnpkg.com/react/-/react-0.0.0-experimental-3d0895557.tgz#0c6c95681bf93e023f74a5448f2261ba99b41c01" - integrity sha512-/5nwNTI6QypTthi9rRbf74i/ac6UTf3syRrgJpkzV52470aNlF+Qq6D6e7kFiPpcfh3A/V6vnMCPtmB/rNnElA== - dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" - read-pkg-up@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" @@ -9495,10 +9502,10 @@ saxes@^5.0.0: dependencies: xmlchars "^2.2.0" -scheduler@0.0.0-experimental-3d0895557: - version "0.0.0-experimental-3d0895557" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.0.0-experimental-3d0895557.tgz#ad5e191e8f13d4b61e52d3fce0a6a42a769eacd7" - integrity sha512-6ZRZa9aolgD+1y2w/vagSzXeoAMllKNBgrVLWdlP2uAHYRsmOQaAkOedqrtEFnqDg/k0SI+uvUhYe5BWOtzFkQ== +scheduler@0.0.0-experimental-94c0244ba: + version "0.0.0-experimental-94c0244ba" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.0.0-experimental-94c0244ba.tgz#0144f590f76a951111fe9f93ccaac7e5b674d04a" + integrity sha512-F+eZM/SpbZj8Ugh7AU5dWydx/iwJwI91PGAEEtc01cvO28ojXaxEjBqUscKNNNJM0xUumoFmmDmEOfAr/wKyoA== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" @@ -10468,10 +10475,10 @@ v8-compile-cache@^2.0.3: resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz#54bc3cdd43317bca91e35dcaf305b1a7237de745" integrity sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ== -v8-to-istanbul@^4.1.3: - version "4.1.4" - resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-4.1.4.tgz#b97936f21c0e2d9996d4985e5c5156e9d4e49cd6" - integrity sha512-Rw6vJHj1mbdK8edjR7+zuJrpDtKIgNdAvTSAcpYfgMIw+u2dPDntD3dgN4XQFLU2/fvFQdzj+EeSGfd/jnY5fQ== +v8-to-istanbul@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-5.0.1.tgz#0608f5b49a481458625edb058488607f25498ba5" + integrity sha512-mbDNjuDajqYe3TXFk5qxcQy8L1msXNE37WTlLoqqpBfRsimbNcrlhQlDPntmECEcUvdC+AQ8CyMMf6EUx1r74Q== dependencies: "@types/istanbul-lib-coverage" "^2.0.1" convert-source-map "^1.6.0" From 42ed300206057a0fb867bb6b91850e7a46668416 Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Mon, 17 Aug 2020 16:48:24 +0800 Subject: [PATCH 083/116] [Import Prep][2/n] Remove graveyard (#129) --- src/graveyard/SelectedEvent.js | 47 -------------------------- src/graveyard/SelectedEvent.module.css | 11 ------ src/graveyard/contexts.js | 6 ---- src/graveyard/useDebounce.js | 32 ------------------ 4 files changed, 96 deletions(-) delete mode 100644 src/graveyard/SelectedEvent.js delete mode 100644 src/graveyard/SelectedEvent.module.css delete mode 100644 src/graveyard/contexts.js delete mode 100644 src/graveyard/useDebounce.js diff --git a/src/graveyard/SelectedEvent.js b/src/graveyard/SelectedEvent.js deleted file mode 100644 index 77fd35d9fc5ae..0000000000000 --- a/src/graveyard/SelectedEvent.js +++ /dev/null @@ -1,47 +0,0 @@ -import React from 'react'; -import styles from './SelectedEvent.module.css'; - -export default function SelectedEvent({selectedEvent, width}) { - if (selectedEvent == null) { - return null; - } - - const {componentStack, duration, timestamp, type} = selectedEvent; - - let label = null; - switch (type) { - case 'commit-work': - label = 'commit'; - break; - case 'non-react-function-call': - label = 'other script'; - break; - case 'render-idle': - label = 'idle'; - break; - case 'render-work': - label = 'render'; - break; - case 'schedule-render': - label = 'render scheduled'; - break; - case 'schedule-state-update': - label = `state update scheduled`; - break; - case 'suspend': - label = `suspended`; - break; - default: - break; - } - - return ( -
- {label} {duration !== undefined ? `for ${duration}ms` : ''} at {timestamp} - ms - {componentStack && ( -
 {componentStack.trim()}
- )} -
- ); -} diff --git a/src/graveyard/SelectedEvent.module.css b/src/graveyard/SelectedEvent.module.css deleted file mode 100644 index 5021ee0f492da..0000000000000 --- a/src/graveyard/SelectedEvent.module.css +++ /dev/null @@ -1,11 +0,0 @@ -.SelectedEvent { - height: auto; - max-height: 100px; - overflow: auto; - background: #fff; - padding: 0 0.5rem; -} - -.ComponentStack { - font-size: 10px; -} diff --git a/src/graveyard/contexts.js b/src/graveyard/contexts.js deleted file mode 100644 index acb25e15c642e..0000000000000 --- a/src/graveyard/contexts.js +++ /dev/null @@ -1,6 +0,0 @@ -// @flow - -import {createContext} from 'react'; - -export const PriorityContext = createContext(null); -export const TimeRangeContext = createContext([0, 0]); diff --git a/src/graveyard/useDebounce.js b/src/graveyard/useDebounce.js deleted file mode 100644 index 9637ba1c3bab6..0000000000000 --- a/src/graveyard/useDebounce.js +++ /dev/null @@ -1,32 +0,0 @@ -// @flow - -import {useDebugValue, useEffect, useState} from 'react'; - -// Below copied from https://usehooks.com/ -export default function useDebounce(value: T, delay: number): T { - // State and setters for debounced value - const [debouncedValue, setDebouncedValue] = useState(value); - - // Show the value in DevTools - useDebugValue(debouncedValue); - - useEffect( - () => { - // Update debounced value after delay - const handler = setTimeout(() => { - setDebouncedValue(value); - }, delay); - - // Cancel the timeout if value changes (also on delay change or unmount) - // This is how we prevent debounced value from updating if value is changed ... - // .. within the delay period. Timeout gets cleared and restarted. - return () => { - clearTimeout(handler); - }; - }, - [value, delay], // Only re-call effect if value or delay changes - ); - - return debouncedValue; -} -// Above copied from https://usehooks.com/ From 16b1fc27eaa15e7be51d96ad9e95e76c968c205b Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Mon, 17 Aug 2020 16:50:35 +0800 Subject: [PATCH 084/116] [Import Prep][3/n] Remove unnecessary sample profiles (#130) --- .parcelrc | 8 ++++++-- src/ImportPage.js | 5 +++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/.parcelrc b/.parcelrc index 41b6f1930c9a1..f0975ccb4595b 100644 --- a/.parcelrc +++ b/.parcelrc @@ -4,7 +4,11 @@ "*.{json,json5}": [ "@parcel/transformer-raw" ], - "*.svg": ["@parcel/transformer-raw"], - "*.png": ["@parcel/transformer-raw"] + "*.svg": [ + "@parcel/transformer-raw" + ], + "*.png": [ + "@parcel/transformer-raw" + ] } } diff --git a/src/ImportPage.js b/src/ImportPage.js index 3a3d83385f72d..c12ef9dda653e 100644 --- a/src/ImportPage.js +++ b/src/ImportPage.js @@ -10,8 +10,9 @@ import style from './ImportPage.css'; import preprocessData from './utils/preprocessData'; import {readInputData} from './utils/readInputData'; -// TODO: Use for dev only, switch to import file after -import JSON_PATH from 'url:../static/perfprofilev2.json'; +// Used in DEV only +// $FlowFixMe Flow cannot read this url path +import JSON_PATH from 'url:../static/sample-chrome-profile.json'; type Props = {| onDataImported: (profilerData: ReactProfilerData) => void, From 89d5512c903f2c45eff768b9148eb355d570f8b8 Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Mon, 17 Aug 2020 16:52:51 +0800 Subject: [PATCH 085/116] [Import Prep][4/n] Fix Flow errors (#133) Summary === 1. Fix some errors manually 1. Copy some updated ContextMenu code from original React sources Resolves #38. Test Plan === 1. `yarn flow`: No errors 1. `yarn lint` 1. `yarn test` 1. `yarn start`: Everything still works, especially the context menu. --- src/ImportPage.js | 4 ++-- src/context/ContextMenu.js | 38 +++++++++++++++++++--------------- src/context/ContextMenuItem.js | 7 +++++-- src/context/Contexts.js | 4 ++-- src/context/useContextMenu.js | 31 +++++++++++++-------------- src/utils/readInputData.js | 27 ++++++++++++++---------- 6 files changed, 60 insertions(+), 51 deletions(-) diff --git a/src/ImportPage.js b/src/ImportPage.js index c12ef9dda653e..920ff4afab21c 100644 --- a/src/ImportPage.js +++ b/src/ImportPage.js @@ -37,7 +37,7 @@ export default function ImportPage({onDataImported}: Props) { }, [processTimeline]); const handleProfilerInput = useCallback( - async (event: File) => { + async (event: SyntheticInputEvent) => { const readFile = await readInputData(event.target.files[0]); processTimeline(JSON.parse(readFile)); }, @@ -95,7 +95,7 @@ export default function ImportPage({onDataImported}: Props) {

f`ZWPEhg5ob7!T z7`%2y+Q0SQWUuwqJEh zwuo%N-#kR47MA367~OBu4+|6fe^e_B=8cGVBW-x6nj2@(1u}~Z&5~^^t^0DxbgLBM zT?#0si#Zj-NTg zuH(<$3EcK&Ee@Ut1|hwqR=}5-PYh`PGP;J~J z{Fm|%cOUQU5zS)QXTv8Wsp?NrepOpmKbHK=`7=rb*$3D1s zEdqfhJBaurlfq5ROy-+RDUa#o+hy`?}7I;LF+^&HN^!<~Qy>$`QzC?YYs6r9WGr zXhrNcYK?;%73~>6hr(TZ6jnogc)hp6ux}RRLVXl3bb$cGb$z!#{`)g#U;CFRiDi#E z#<}E}T?siqpCYS%4+S%y(~FUZ@f89Z289JNMO?eoGnj7F8KLy^C%!1&V2k{~t=gy; zK9e-6(gIm^lft128^}w5HvOERg6M<_iuby>UOv9Y+`aDDI0*aT#ds1stnMzFd2c!F zQ37LU+EP}M@oZ4?@29P69NtkEjUsw~xn^bX0d@2?V-FU<_te z(DT$iQH`Vu_l9P8+0nWA-JgmyI5Q1Rp`VP0Gespu-cdn_pGI>3%Nb0V}4Ui*b@%cu#GLNKE0+9aC84Hv5?d z3(MPS(K1a{2fk*@MS$gNgqfJONNv`{UCqq*KVqW8e0T4D)p%?+$OCF5652G)#dDzT zP8EAM+p})jceI<8Ho+h(oQ3CtwhkR?i7TYS4JD0&m=yXBe&+PkC_sTO*P=>G* zy+_)<-mjT26jv`9g5Qb6zg74H4utj&j&7Ul2RAz~nYUh(jey7nqGNdur)f?XGFXW38_b|$=uFmObZz^nu@Fu^OnAgbk&QPYwuWURJUrbKb z{d)qqb%zSI_%&}8h@0qv9StmYE1Rz=1@x9?RLudiw|2pmSNkOY3zBeC%Dtla2R{7! zQ2&m*`N98BY|@%rr0pW15-3iJA-QbXj{Jwb#Eysl3sqXfSH@(K@UK<&Q&Bjz$FSG` zvIcJIo`*oPe=r3lPb8m?2H`y#30I7?{AlHVpNS$awTxt>&dhvfaRblhJpPx?i2wJ9 z5YB9)AtRK*Am6yc<@8p}CNX?p^JuqR;=)>bh)kgXK}mA~g|G-M!N6#3GPh30kk9@4 z{V)DYgJ}OP3qjh)%CIpb%5;c(wsbC9R9Y=LHEwLx4h)^j<6Zgrt<15^XOY3gwb zbdt5>{cw9_ysbjBWk8);3$hsz;M6aPwEwpIu~^|bjKAb8E!ojFq6*Hn) zv_u7LPFO(~EQ6&8-B~Mis2unAI=j~Mc5!t2w&La7Pjh@}>lZL3C9Zh>3~XU^tot_7 zO~wmp64}x*CX}eI>$u!fJ-E~Q=7y&b@Smq|yx`ILfx>W8e%7QHw|moxfA*AvtYCNF zg`aRc<7B8K%I4+bZudpQrhWeEh*}ZsFGKtde+H8J`7r-h&DY~pfO7$@Ahd~ z)t+O&_e#P=jKZBnXGR=Gf{nxEsLN1Of$h<6eb0}=e^F(xe#@E{YdGV$J4XZ6gHojJ zDWIB9>Aphj5E#7%kyrXODK7a-Z{94`G_X)4NCB4#4fW(42jCAS6c#$Pze$!jI9u|K z4&?AzpJ+m=9G1&a&6*rht+)Ipbrp#OJ@e);{scFR8_+#(__A4 z5iHJPAMy4`YLgcz7vlvl{cJtAgo^r5#5gje1@Mc2p)Q z8&T#3sg?eyBr5RX^cNxKBMs)`CA{qX_|u*)qg@I7`JaSAjvGe`4XeN--}dHuf`y?C z_kH1yu~L#^^4S3&wt%vclQq@Z#=5fa{&E>rrJrUC*?;paj#X!e2ass`=PSEc(`&N` zPD$&Hd`qJ3dF`QoNx^R85d_Lj>w&RZXoc=R(r0-1(i_`ivo@D4IX^D;bri0=Ovf_m znRU$rT@LElN}i1eg4egH4cA($ataC}+qFySmNbG%4?G5h7w5x-S|Vn`176zU2{j;v z6wP^e)~H%WdW)pauRgzZ4hN<=kv_<+m)^tLz)DWIoG+@?3#B^ig7`ycvFhb*$sTmf z2!{$7)>5q!vu4^69t-A^k5NI%5-trGMmY1pulpH41NK= z-#eJVhU_+w=ZtswJP>E6{~LwF|*+OOcqYjaiIWGv9E{o0e`Y z^43`2%}#}UW4bXDl<a< zT#IXqI}|IW4eq71c#%SjOG_ylToR-d_o6KhEfjYT1P?BSLQ zy@T&r3E{X@4!<0(l+(P>*(#}+{>nzA%$Jd5o5=_n%_R&>F*O2gn(4~vR%#5;k29ip zI4#rvPNDO@&H8L!y4rx-mrSPB_gsrZm(P*f+ZqXG3Bv0DQRLo&g@_#EDsQM~Ff(>; z4&1Z5O@uKDGu-pjUQ)qSR9yE^1hH7iagb4zhaWOLJT=ir#)k@fAuu7kRf8`!y-*y7S0+U zmc{lJ&|QbSVxSZgjl*khiN_eGMD9*y0hH z`s=>Q7YOZ-C1V^|vfDsYx!`F4hN{Z$uCb4a0yX7H;F8lwz!v2TBdbR`Zl<~QFPNkl zT1QN8ISz|SlmP^$mfkJ&Q40EFDIRxD(19-l)7U`4UGpX!=WpCNaFN6ACWc+xBs<~l zSS!=Dp$lO+qfeQL_jGe*izUs6ZC-Ah?c1<^-Ux|(iaHZ}bRmj`Ijj*>sHu#UkhYc4 z;Dv|)6}}xeBX8BRN$va?zZ91MB4F({U#o`g+l29V)P%j8a9k?cU%Mmk;{rDI1-<}^ zHCiD8Q~EeM#{-g5#16K~`5v22EvF#D05gKtAn<_{uN{k<-_hDS0YNVZT7WNKfN6H^ z^Y%|=ShMRqpzmoWD16?|h<)TuA%~Ysxg=WXVa3zl!B z7kv9K6|`x6&cQ;PUzR6K*R}18!{P`r(Kfr_b>dMA{sxY~HMe|8C#D(}IqQt*758m% zOef5`Hi?1SixtZ29R$m-x(@@{ae&gXarwnEu zn+e+OHt01Q3PL_H(*1cP#@DeF7^&R#c%BSg?eJc(xLyE#`JC@iiXwsjQNo~4g>JHJ zstfj2iw%wo$TESg_S3qf2PiAK7_>HSX3bed(S(9^CsD zW*Gb!+FiBhdU;ZWiDY5CpG=}2WLQQ745TR-MV}GfTonOg=+q1W|lQu}t0(wkV zT+(>@T`R@32V0qCb#$L6Xhsp8iP7H6J=TsZZR$(e#%@#vpg67UYC3?FQtCrW=l&wk zT-ip$FgSyYa1Knl+AkJU@AuCNX-`^v9;%zqeS@4I=dTKSZug;Z@l%|1NL{P+?P0uc zbJ`PT2>VF64ktAfoZSYMpv4_8A%^X?^A)qfga^8rPR4nU?O1#Vj?;yz^trsmP%H`Y zsX_(`nesKV=L`C9%y4S>or{GK$w+_h-j(WixM8T z(W4LwMSyMA&d=E%mJ`{o;+Eu5?Kf=Zm(3fye0Gr(LX3z2187rHS!vKfca72lqLckw!rQ4ZSsF4vc4GSl+54@SU+4*ox<~0neO=&!aX>3>lfv7`j`u8oh^Sij&rYkrz`2 z1_rYbojh;bi)qXvb2Q5@L2^jIUcl#t`zsQWJ4Tw!V~}7ojiq=g^fo%=rD^Wr3_YG9 zB@(xHjD*vxbvXyZYEr?j zPnCPEYS3J8l{G1|T(Z`UzlILoIHAFqrF5{l_g*QfFwqf1N<9=}97Ap~1BBAeL}e;@ zpP3VmPbcv=rg21k0%4&s$j#d&pFr(hcET^Rt69U9xr+6V&ehB(8Nud3U zrTHHR60QMh3-r-B=q5BLF@z3KR~DE)io5)#<_{hI&RJ#I6$k3;p$Tilz13&|OLzPx zLguM-A8n7T==NwGYWKI$Es<2gBZc;G;KWOE=j zuwLI_YET3mH_gJdEj|t=#&5R(>)Ge{$bC;A?FCHk5JNb${gOozM*5Cg8+(}qo=GYz zoZ^qZZdzIC88cOsv}Bw6aR}~Z0tOy6&B9$vVjBZ)eN&t?B`MI6PUtCyXLE&wJ5ZUe zbK_0rf!+#l=5wRo*u0=~K9^LMk-cG{awnhp^q!Guo9SbbVbi--Oh!edN8mr8>%{>M z2uQ#~`*OiG=2l7i%K$u&I}ns z>_7M#Pl_{$>iyV4;*xClRd3B6P|rS@7D-T}wK;jR@n+KLkICyTry;=hzQZiR!*v55 zjatr(k_Se=XKDY)mNtnrveUcY)R*@@My8FO^-}R(=0f6{3itKK8a=XvdSrdbr@dAS zpA|H0BUEk2_D1@?HJPLR<{xdZ&(MUQzU$Md9Ec_G|7b_IX=5h6@)iskEUH&Eb##fq ze(0ns|C&KXNPJ5*`#`Y4c@heNJ%g$QOPm^qm{!(@KVuX8RmNF!)R_Ct@9s$Oy5yLE4T}F%4D!xW2Fp7#C|YE59Vzn+D|HC zStVlIG?;+8x}H$bO+!dsp=bNfhhGQ0B5;CiLqhoT;ws{?@+sWBX~6(|&C`TW`+uXV~7XVcPEcRinAnT}d0)Od$~}y0C3S z)^eng0v4tAuirZcj01RoX4oZF)W-@;bA*h;q*s1Rw-wJ6kIel|V)!474(5ryBn#FV5`Jao)9$wY{*A;yvi?@mCA4Rh|#v+F>>I$$IBZ_OAqmXadx@NKM9CAIotb#L&OUZ zpJ=T*x33ib_>1J2LHV>IMxT8zZM_W8vd(mRfSnWvRB*w(Sx=A5fN6f zLXVs+{Qeqa%sJ{L+zc+;oxVu&_mkd{Ju=|qcneW%=m)Ag_!#n;m?rbz+GbNcvt&*w zuh_txPaCzKr_437xS8XR@m!}~Qjf_wGzT2r{qQImdkx^&&! zOv4#lXzBAT@W3g6%De2>dLyxCO~k3-Y1|?Etk#If+I8V01XjU3_Hz-bB8n1mxEwPo z1F3P2?d6YTuHw<9wKfNDtFy^>K5v;nXPk)?xmDl^PlxK6zCJZI`T7)SHu#+6jLiv| zcnF%Qewke>xZ3=X%`SD5?~D#yfyhrdx-+H+$639)sdNxcHGFt$->vE_JhTC+U9K{DS+{mE1+Kom%WPS`B-aaKb z=qUQ6!bPOQt5>+fgi`J@Je^RfA);I~I-h$CZ-`eK?9sUfYs|)JZoYb*C;D}~oEIF$ zajLQXVcT~$31q_*d8PQIs0HBYkyF=LvZ3d0?A=*XBC4M^gp!^&OpnTuzW;h4K!5E6 zr~ec8#Sd?0NV9Qo_RJeas-ft4H}Gh+XzN(T*j{M})v*&-bb9w6*~!-n#ZBE)@Ceg1 z>A0vIm!a9>=6A&xV^Hd+I}OYvFT98 z=Y-6-Xl5+disF4S|Hex=?M-yUO$L9(z(dE1ohH4|4EcAp{3QT&n|6|)UzAezpY%eb zw{JKjkhz{GGdL)96qxoui$k&+K<3(kn51e z8ty&KBCVxJZwp`;Cj%08Lm61Nb%vXVanRL)IS0j_c^2Y}t#T5LPyyEb(aS-?}jjbi}edfIHg@8Rzb2V@aBE zSmN4vMK*zCdX3`jGI+aSju}G^n+z7-X}hJF*y#>!8e-5^Gy4u=y^-vDGvvk+qWRBc4!wRuRGD};yWVjIi?%I@tl4#3)*pCIj}xbe z4T1Y_LIciZ>h6R3r4rWY@TrLhX0HTS_Bdb)Rt!SJFOQxd`pd|jN-fE|c*ugZzhu;k?d0Qq3G?unRl0#a{kXiA!S^qRS8Fyl{8aXp z7`p1e%shFkCY}kie3FK!@6afEwHwjA-y+}jjrGX*HEmHSdVz81;iJ0^G=+(F*T{K$ zZC%w^1TA%h@#dxxiD|QO$1|wm;wx$=h2!umV88$JbGt*-=i&0>%$RpN*y40u0#ZP^ z-N3Zo#GzcZ8Vj+0-5M83_M)ef@Hn8vr|EN!1h%`^cj)l!nWl_Oa#gxwpBF3pZ=ORB z3jB<)5G4}c`Nie0QFz&(*o~NtIfKXcqfxJU4mp-yoFFrgRd}O)%JL$_v}qe9bB7+g zB-NgM&|DO^kB29g6V<)XgHy|>d+!Y&N0&=0E0m-TnFX74yC4vQPe&on>x)3D`Vwgt z>Wcy%>R*PRoO;SV=k32dgf|DA<_j{v;5zd*OSt0Z8tbiA?G8RfYZVr&v%Tldtn)pN!S1P& z&u9ki^B%537MHQG4&vv|&w?LnFQuJ|&r!twro(z321JNHVEW}PGIWj8^j)qWR600@ovX!Db4 zDgSMP2Iy1wAtbA9FsUTdWIzk_oZ{Zi1^6-Lcrd7U4@da~+A)S(cdS%9B+o|Jv zdcw^9l*>NCL%zkADwVWC0i_s91&{P5KhvprmPq5bQabMey}_+=DG;bu>=#3FPcRUN zUHXwF8%bNXadtdx zdhlZBl$_rpn$SHia^+#^v!CC?(&VGON@Aw`R;pS}txUNYzv8U8sq=YQ`!! z3g%=kN%G60mHK(2B!%TuKVCuk%=!si854DEn-*o&iYzSBGiIG15w~&2<@L<&J%IU9 zYqM)hnO7YC@TloVz*|4Zg>z2S;bO%3(nP;D_Bo!L{YqMPyNs!t&bc@leWgmRkbW*s z3RX`&a9A(LWly`Lf`u49DuZ!Wc(f?G6+$*{SBgmK!%ojMT2`(n+pENWl?pb*dUNvf zw`FclRivOl#Rx~^LCvbohqRPOzYZ$2F*8dnR!)p$ukWnDAvSrAiTldtS6?iCN@ulp z1Az1E60XtTZ3%<=*(0CaVh!5erstLh=~vwWa=9xe-S&vg&#q;)T%E5hd?;w4es)i2 zG&>`=6J4M>lw$g>z;flr0d~HdIhr;ZH&xgbtK$HC$8`(0b46l01jK6D{BWP9QsT+M z3SZ)Cb%2yqotAnf#QkAFMP*I1jk=nqZuHV1jS|Wwpy4CoZG?C5KHvUbOF4IKyr6yl z9XWFDwR#;z)Pw%>_0}jRT({3I*APcYh!DIo@Zvu%z+#sx(JF<6tcikR zZpHYtJugbbCFMZ}XgB#mp?`(fsXZJhUd=RU0u#ZHSCo;P7 z8%>WOp6fsic%(zAZ8GV&c~ly4y&fo&<-o+J%X}Q{n??N{);_}7L!wWGVZ5WwJW(L_ zFK8BZv;jh5(S*+Lj6h#XMA%?jT{#hG*mK9e8Q0NH5UVZ(A%$q~^_M0860vl{SP(p}p#?ffg@oNHOT zthAMz&13mrR98VdHp0H2ev)fL1>)9_dxENFci&Fs=S{MFdsjyurl_v14WwpBXE*&l zWFENprzkC7nH{J0qBhfrZ3EZ%)!Mr(w)Nk9?R`31sh2jKERQ1n9hG4%XK9x~X?iEM zWgw@K3&&{BvR1YJE;Ds!J7J0I6pr;s0~|IlBMA?ZosJm)0#C>p>!EP~wUfM@A1<$b zsbe*<6ZDeZ(gdCpFA_DS}9gG-jHd z6M>!6z6dXuG8-d|;5*7==EmBS&X~uqmQrqC^?h*a6FzXV$=F%igS(VX6gqESJVvRN zsR#t}%bN^NyJp1Zq!=4$12a8MjM)jqDWiLiCBP#}aAy}MuV?S%=_xmK=%l3`_&fvo zMGF7KpNxn+2yE=pgjN??>TU5es)xR)0Plmn`yQ zJ^fd#>Z&eZ_y5ADD00y6n~b|^)c*mTj+i|8lN(i=G5!NuGQTX+{=Hnr&#p@Aw z0fmI^Rvn8so(B)B1-$AVF`m`KoMNtqLX*F}BqAFxzqsVM!#$eo)=GHI9FFH&+Rb=Q zs^jusW-UzZOtIY7@%|4Sy@Qesg#SMg>3=t|CjH-mXc)9X8pM)23={^n#r$1} zCh6V#uYUU`SvA;=Bwa}5z0jaNvBSNi;f`dUsAA9X-$$O{kl25wtCIakf>%k+gJdp^ z3_%aC^~1s`;(_u_T`pq_%jNfx;YDha>7YJnwnYc)ommVLcb8%WRP?W?V1+)H_#gf~ zZ&|3Yx@O_@#@cj#I(>Rqz7V#_uf-p&Fl8F=f1aU{;$OgeuKPB^bxqGn`4y>j-p0za?0A*0^e4&EgS=Br_cMCq%IOU;gY~%kP`y{rYgv~@ewZ#FB zGau(P&utFfX)W`t`S~U1*?5~)%8#jK99}j{h(cHTm*aeo1JA`pM6dk3xG;7S@`IhC z2?_+JJKpJjujf!Za%sww#2c6Brig1{C^z%`y(hA?CJ{$*L5x+5G)`;K(omLR$kN$} zHTona3U(*eP?r-e$nk_57~X?yg7nAwYEl7{uho#oHi^b!tS~3w^kbBUne#7LlXKG0 z&g!qHfh8?afr@*O8gi*JnYdW=+kEpPfMhTX2PcLP(T6ZnQYilrS7}J^v|hi@-u6&z zn??&PWb#bcQFP_h#DJmkv-oDx+Scy%u%~f{8_tSmgK3g_C8z8B>xBlg_ErJ;h#VK1 zgs=Eb-t)4EG?xV8o0`pN(G>vTr8ly=%)znv^i68~+Oe6__jsUzl|BguOsjX*$GKDc zP^ciuuw^+;aDow=ov5>DPYzThb`{LZ}5}{VQZ)CUE;O0by`4H zPC?P8;Cd<7?98PFY`MzFYLVI;P*|PQ4wzr`RPJl>A9csMYD3;tzj5wZ;Q{6SY8Eu8 z4)=RoMUiN-+poKLRgeaQARwr2EYtk=M#aq4F43dz?W^~Uz6x>agvD9M=x^pKoiyJ6B~PQtoi6F+rL+@Dj2>JqFPi zg$HxznF8uC$#ls&i=AJCv_i@&?tLb=(0^#e`*v`8SxL znXVlSP(w zk}HTSYV@V(*#53RAXYzYVxkAE{kid8oM=vs{BsVHEj#(lWA}S2Kd#w=z{76$(VU8} z^`Cezo{l*zd9u8w>*zn zquc2&!fv7GT^zeR>l>t%%l)U9gyNYuu4vNhJl^t2rK#r`HYY0DuCF_05#*Nk*+n4f z@QqpnQ~`Ffqn(b=z8>^v)A1Cn*;%|)_>FC*?M?p<;Oy}bX5S|FO;^v{@<|!*XhHfo zh!B27mO&+)WE?d%@V-_}w(%wmrz>iy2`O{tX%-=Qd@XhXy}r=uXYs=tNU&D>5aCP2@&4z}&1rFHKH0)IX&aR0?8^^nv z)l419YRF=npttOolBt8BqlbDwSq@IFWS=X+p4wyY+ASdV|H5Ul=PZ^AmzIwd(9!_@ zV(Sl!xM!jP92rLWW{{#PZjsOp#e_4TZlFajIb8#G#jpCT+X4660_s9Ra%Cd7O-ny`BRpr$rN$A*K&46Q z*2Y&L>_I4qL&0Gg`Nh-@0q8d}eZAYE|K*Of+>>rICmpc7QTaKx7h?AMK(_@TFXmn3 zQ?aV(7x=P`i0^mL+(2bY4@=IvXe-X3^OfYFQx^zpkm6c-k{ra(e{du)9LlRdiC>OT zt7LM%d9EnsT*O6Mpp1E0gj#U-;A`b=gV>t09f$Q)#9JMS05v=4blcBSlVo!DWDch` ze22usy3ib!7Cy5BygNE88BIUvTR|k>T~=$jevb*M(XW~9;6q^1B*HN3unwYx>fJ~y9NNlL?dXMNUWo({9un}cZ3(P9txU(b zEvkvP&gSdnLGK(0f{*SWgzfv|16u{6S&anbis=+;KMiu7z(6r8R`Kpt$KNL$2gqdy zLT%04R|=fYFP!ep#%UY~MQt1x9CLIG7C$(P*iaiiqSL*O&RU8n4LwJHur$$pCS&yb zt{&I4A933n)OSg!d!3O}tiBZAqzp2rVmCvdirn&Lb+noliZA?Fq}K$YdIl6kazERs z6PktwR;eCu-#7Rv7=XHd(gc&ySy~yl7*1i!FKDK|zC~r)Ufbe&2l1IV4&}hfTj@Xg z%*bC5Hu|?~R@)7#_9(&fE$8|K8?H3W8A!5Ou|wQ*;B!2>)N+C+jiziyxi^tCw}hsd zrdR-YzZ&qnL0J+he6!w##)+Z*LVag*B~kWnnUeMuNVAW~*zwQ{BJcnc_i{QoK2+Uk zsla&o^!i1EjF#9+dfwKvxYOS76(i^FI$7nwj+?Te#+PaQ&-ruw5z-kJQwpNdqKc@D z88Yt`_Iljx%+ESOFGS~wTM1vGesKN7tbC1s>RcuexI~}D?plQ13ZF=pU{ha+obQ@c zvEUI2KGLzE1Qbo+iGl(wEl5NJHeh2cX(G*W$>J$cAMGlN3+|=-_8P6g?~9c|p!+!x zB4do5*y~};RrZeQezhSnh`snzmgU8pBN}461N+RVk5BV;^!AuCj;vUms4`a#KqRX( zpQ=Xj$7(5$$@rT|EF#YLXi3YgE?mp(t?lrXMZ+`hJt_D9*NN z04wnZIAc40;fpv2i{i3$(yR-wai*6AjD8|lxpOI@60cqwQ|uaSdNbfTr=NWnoIb!3 z-GONeoXkE0dCgdEMB;t)Dy_^T6KzlukmOz9A#uYnEH2RErh!~RPHLfzyJxNY{{m|E>!VWkjrn{Tg3U5dcFCT|acUMh3=)Exj=X=?7 zJ6wMUsyY}?ZJLxNMab)yQ1n#KmbleE`Z0Ty^~FK&dd!9z(#As!qWm5iaH&`_V)*>f zP)$eTerdv$6IZtWB=hXtBpw$|NnrrJ5|iBiuK+`tqYoPmc^}E3yz}M+T9@;^+5oyC zIO-wj8Jko6npp4U42Ng=&av6dF~HaPjoj|hE@0S>4%rmDQQAiXeeEgjFae-zjBgO@ zd^oM!0F80>+@oovM0z1Ht(W#%{}4|9DP%d){euYp7wY&ozW-;KpVs7GHSj;xG37is z&OZgF|8CMtZyDWA_%}L;%C@?2I4Zjyl)YT17pw@~`FBnu>AyI@&PwC9{jH6qrIp4| z;DfZfD`@P{+P{=pXQqFttNR>7mX*9dSC?|;pg~tmCx`a2;PvelA*9wu_U4Sze^T^f zEuPfUnE9BYmT~mJ8Xgi@Us$2|5SA0uz>m1p-i@og&)JY zUA{vD;r-cfLMmsA4J=G;4Y8L@x;&W5S5OAk`3EywE{Z8+PJfu~Gx0U$JN73;yac2~ zH|v>UtyhwT{)If2VUn{<*eCM7EzTMf&n?_{3(BYd%o&=Qe=cy;34o41AEXBxl-rmr zgndw$V>_NJvB?-e$j|)Pdp$eX_;JBpb*_0+GBuLw^6izRm-=b-CS&8%hKp~nU_}6{ zO7QH-Ji=k!>4S>_2VojqQ%EQ>3SjGX48Lf2eefq z7Gr%p&Ks!%RJ1UDUD=YakqL=vpG9F(xevK}I4sGr+;J>%EaL-HFCO}9jKyKQ-?Q|P z3zkruZ~zDYnVZl5GZ3^EK#;D&iZQ}cIV$qadMswUa-KaKdEAdxJ9cj7C)d;7v_K6Y z92VL6^Eu}wx7vHcj?qtkX;;;))tpvLdGXx@^P|_yW-_nqXtM8|(H=V5r1V4PrEb%C zz3$BDeF>}Hw-!z_m01}5dL{ne%uezv-VIBYY^m4MvQuekY#DxYzKP%qi}WgV$1Gnf zd3^PV?90l+@)FwRJKR?y#W+CBTf}0xWXSe*QT6gxaJ~c={&g9(tQ$nfPWji-(_S_k954~2vyCexpr?AcCbOejQoHhsC|s|H(d^3V#(SqF zvK?7r-QlMLp`Jx1%v^q%5z4e>5y{DsVq7=)H9zppjWYXyY~GyE3m#8_@2#=WKKf%8 zIsekPhHp2WkW=`X! z_`^Dg#Wxh^q1SF~J?j|Cm)0L|LgJX+6`}S-XONkrbmtU#vf$k&LbE)tQQwWgCb%oJ zsDiEb!*vJbrwXS-ak*~9r4)=vcsl$-v@BS#Q0Uv-1M_g^s+^6=k&b{q;6`${C~&?U zDHi~yrqjk1&6$RA?`I!iyX$N!gLFpaD>e>A3%cO(Sger@FQH>^3GPg*k=Hpv=mbe6 z%I;Ax;7(Kt$=bs{lhIxpLWAgq8-#IJkk|ePjgkIulkm6Ja4TncxlM;+LS~5AsH-(E z)JIj=cOG!9Ifff|5zyUyB0WcdMfzU0NtoWlV0VOU_IpoT+*6baznRzwL~y`%OQYms zH^gM|YCK_0&4(&U87`sj4gOjF4Sd1g#Agg00f(bwhuUX)IrlQFxlHu+w&QHIo8H#f zvY_Khaf*U&NUPYe{VzRtwe>zZC}5wpJ)&IT8H?M%4wq5(?;QQuMSR_K_38zoz8Z`wI|lcdv$2crc&IuL|x7*f?zR-6ZWPG3dpEFmoM%cHFOQ!QBFS4tsVpD`@o;vqoyE z6+#%RW=8L#?+wnFtoMw^*AtP=4;dFh`vRiDMM`3;i( z_O)E&m~L}o3mPclmoEdzu3!$PGGoQqc z%BaS9J9E%_b#i;98%2NWc%rJ+Cs3typVj@HH6;aPzgN%^CI4crDP`LYt!d9TKUWc^ z)7eF-JqoYvT*KMyBDsVLm~@<%13$-;SyN7vp{w1MCeikAVlB_(ACdp6t@PEiuSp4` zK;o-$%eL5W*tiLr=h3|;Pllq|ljy~UnylNjez#C8G`HgP+-cW}$mDT*U2Yp^!R=7A ziZjmrh@1JHsj`o9 zyBJWLe}>=8a37-evEn7hpMR3W3l7d(Y-p5 z5H@_*WuhmemvZ;v3?GKijB-K3pTN>|&jZ#W;HH=C0Cw^y&w1vX? z$Xa+>g0}oIY9+=_3gO{L={|?!DmEYrYT0DnU>E#cTWh44U7J--$^$Fn=o{p^RX7Y7 zSYyqmY2*(U_4Qtk3Q5M6>2|srk9I?4rJ7(LG__9^&xo-2OB#_8HCr^|jMfNL4pz0E)!Rp1Bnv_G|L@bk` zR7voZSQY?(Zrr$Ms1;mFzWllKGwvm8pN(LgbYtic6|S1a2+c+8da>ar?^tOxf*rc` zMSe7@LC@u>K#2_lm#6+8zxb}}V%PgxNp`_e)^&2Zve7kH3v=Z^8Y7afT&6g{84hLw;vJ!kuy~!c76a z6@ZZnePCY=3T?JguBAHP(&L9{%w7mv2ydTeLB0lR`Q3V-PJa6@F#RjIgg^X$2cwGr zUv*v`^x)XczhgSNZpK?Z{M(*4-8pA(-vYHv|0f&$AEk=ap>l1%L1^Bnq3MadY3(uO zzoa-I@86_2YfNyK=HdPxALRO8=Aujw5YSng#)e|$0v&%~lbIxy4FnUnwuXeCpI2ot zLB;Bu<{L7_{YNoB2cw~Fo`4B1B>ef;Eo(7tq2Bv6MZE5M6Q71mAyN%hmA>^2^2(A*>_A0K^k|MtSKF*yAEE$qk z!uL;9?#y74++l*!Kf*Lpd1=6$8+~>SBRq@ME4#pJsr?;*G9xCYFXxP?KMgxdAIUAc zA(zToLe}KkEK3i?FjI|M**3)RyDa+3k_Q{%lN5orROIyp(IfiwY=&Q5a0gJ{uB zKg6$qmN+{^!;0tZ$y4K}ErWF~SE7QB-(Py`oz-iJ#nUnCiikN2mb^2BnNRo5{=zJ- zOFMqcDLMKv)c*o}_GHO4ddKoSk`xD(*ay&m)!@>+s6;8~j-*7F`1DrlYCklIcp zcQoF|%%pER`v*bPdqN*@f7+-Cb#{{Oxe(we>M>hy)fWik{I>n@1X>BuZ}4NN-kiH4 zlGX1WZHh0;i+{K^XhZp!PwAe>}r-C$c2$5DA({ZHvvJw$G#YZs{1_9wwqO^W+Jxw zKH>UhPTYFm$FLwobA>+OxKgT(2{pD)P?-a44GVx6`n|3ZHY|U)?le5m#~b0hIP`I6 zfzr{(oI4{jLCckr(45yB-8MQ(Kn@|7I`7aP9{5}-wQNhbV{y3C$}~7~=kTEDMFb!4 zyoxBY(Zkp=xw>tt7{ydg;!E`sw8>LmGfVnMUu(MbzbRyqeCWFV>v1h}DKn8tf(^fq zlNY?PU+t@RE$(fgh_+tx+`4PZClhj7KFLMbo(2m)6L-{G1}+Y?t_#E!`-l2Rtw8a_`I}}PV9uMMEsNKAe)Gt zhP_qHj*eE*3DnI^Z^TjlV!u&ni05i(AN!(6a{a!g?}A-Wb9X0hxx*R7bbNPn%nROi z)`TR-iU)D^ZZawO`Lmzv;*AMg`Xm2HnVB2mKqb*4{Q}PAtk~$$)9({JOtUL?et26> zsqQi3)?j{)!F~UEk%SgdYd&%t13nVpp2r? zrU`fgU($x%L6nhH2|e0IiUzBdACAn3bgQci(GHRfZ>YQWvt^xTVaJTVW7raAb>(UT zI7XBC9~U5s$6AtLg>&bvlVb;}c$us)9TP79o}p$gdv~Vo+_g))dTGgZTOs0u!x0hE zJHUDGLm%hTHiZ-!A7*6-p2ZEWNh{OgfcM{2WG1S43LQ+DVR=a_+_j;C-OtJzhqSvs z%Hhyc*F=8t6<|E=jr zxitfJB)~b>oZIM@G?n?JELv`Mems zg3rfmWwhsSVdX8ee;8)ajyISCw|cd_=|9~%PnJ1DduRIEJ2oK(jC7@S?Qi80BcptS z!KTHCR~AY?^3_#*AK$YT>V(bn!^OwEnCk>2`&gm1KrMbbWNL-)po4(cCp;($r=juo zoBOb#nu#x=WYPTBa8QhM(jzPX+t4iA8PE4ju6*~r&`(BdT58G^azCR|ESS8daRQt^ z7}>fG!m##wS zh-esJMl-2}9wkOlxBWd^H{g@n{GU9Zg704DC{n{S9$)`D<%MjwvO`knZ|h;P@o$Tx ziqc9z#v3o0M7u^tjbCr|WpC9CR_)Aq_QlT8a2JLTEA75bSc4LZUOj$%NL8fG){!?x z++Udc+oBt`%LJbJS*`Y57^@!Wk`HE_(?fOHfg!x6FP*$U=Je{00TCu2$-btpaA?iq zDx<}HHMT;N-N3@LGq&N2b5LTDsQuM-k)Z+*?hiP{4Hb$@Hd2ch>b2*NQD81zj z_U^n2+l-oZ%^`|=EL%x>v(P%7P7+{257O&JY2Mv1qz;^3HF+AE6T5(Wke%U}KF3YM z>U~(OBJ#!aE(5-L{&LfeMC`8H6#czcYiIK{;XXwU@+;0JbOSrGNHSPdA{|4QMWw9} zE{P^6l4D7qL3b?ep+n0PjBxn@gmYYy$j>OH*JSxhyFqBUD z)v7h!<^vIP95F=#^oSu;JvC1K)HU{RF|D6lD1JJ0L(c@O;sNj{B2Ok-eu{Xju^oLe z{c=R7HJ4E%hFCA;ioWj4f9zyaaJN3a#gQ+di5W(K0D1I`^pZm~9o@(o&y4I`BU$xP zVIC8vG)3Tli_-qDEeZe6ImjU4%Lh__5Br6QU0YS282Ua3aeaxcDE`~2@Xp;&{=Ybg zVR~Z&d-^TrcjJ+Z*1|u@MMt9lMk)F_w2OQ&XX3XIJZr<)PL>IIGC};D(b7BFD&b(| zwgCGPtCel;LC8NbCvXQ|gSYTpA!;`9X6BQRw&8K~sq^H!@h8&&_ZRi3r<;nCkYuAj zvr4~f;jU6g7f!_Dj7ysfRB<2dz;AK9Vy<+&U2`gQ)H`-pG798!g@TJuq3@WOLK;j9 zjVb=Xbz_~Kg%8fw1ZUkwT5M|tvUb;F$`t-btPt%C^ z3zava!k`sadHd`~R#K9lqBo1R=WS^d2U^NyGu~!7t+}GwX*D{CmtU8DGk%HI>}k!2 z<6WG*BRVi0pOr`!RZ5+T#cBNtNfvSWlu3J2Q2fY+YxE)4zFr;fK*p2UVP4;e!^U%R0Un@B1rXW<6G3bZfV(>tth7vhaUu zEpz`U-G&yD9YS&?)-_$0?vOBPuG*SG-khp07Ot2OtiS(IXvj8xMuFia#0rdfcQYX9 zQM5GU4M@(2t@5{G17?vJ1`;yC%d2xdxi(MRmo{QxKVAN~gewKMkF4&m66_k@F}j;_ zUMYLu+gWABWUb6=ok68`=5D`$zD0V~JYb3Q^*3xt#|FgM5k6|9^A1b@0ms@W7F(9b z2$LFlg`h1aSURBwTc+v^Wry|KA%ASr@4}_Ay}RBudjoy_9Pbyg5yU#qMCszZ`n@Fh z6zM9KhdJi^+{cyJN;z{N<z@Z6S`zlRW5>L>oRdS2(BkkMJXug;bfNQ&3*KdZ zBtWtR7}oxf97rgYxJ%wRrlfC~HBU%@8Trge*w39*D=e&if_+JTV#AK1@FH`I6=!dS zv2vxP07x1ZOum!oZ&m6(QhnOp|fnnyAOu̓{K7am(nwR z$DhnjL%vgT6bI6KcN;{CmnhAJ@{Nt4Z6;-2cyAr&bK=`BQz$FWoU!+Jo&1g&e0SWO zD!MUj(~E|YLJ|J4c|2&M=q8^dH?$?4>+q}u{ro~@2+*+qE`5s-*4bE0&?8Yd>h*2h zrF8E2cd)0(JDVA6`(}jAwL=M^aH6|rz}rNd&(`ai6pfp*C-}PUSc4l7+`2LRnaPoP zvYU^V?OkRsNx}jMqZl~17;(_&Sfdv&D3__LDua&fI?ONq-~YbI`gZ0*s-K&Sy6y7f zoQcg6%=+0+j+JQ?1H?(5>Vy6whDe>t9Ik&~L2Kbl!PjogdSXj3!NFP#MB!I{^iD1yyF z%;G{8Kq9Wx{y~7E`ceD3p6A2bk0qnOSXgc_81=F6t>Ue>qs2VuBU`aOctqo2iOE8U z)Mqcw>6ZKJgoaEHaeS~7JhF-y^iGp1EB`!S7+D8wxOxxFriFw*NcSRMP%FMvtvTp+ z*m`M|rE>oC(AnNYhBT3miNIF=^Qv$gf%)yJC#$fR_(KsT2~S!E5%RKw{%H~4 zK#AU`hdKTaxSV8;@@#?}1{YmuZv+HKnm-PmZk+~|GTG|J0l(FHO>c3Z81|Xr1|F?7 z+uIEHT8O`(f1f+wQO!i#^spAZcieP?W;|;xCmglIq!&7&Y31#{IV{mx1GQm45ZSKs z8AF32>&M>CbPXywUs6JbD9>|NFZlaaZWz6X}OsX5@s6qo#bB?$2bY{W@P|T zMw)M2L`|rAr@+?VBjP5%;rxZH<-pRf(WWBuzO=w3nxF4lCKn4VQW({T8~Z1B3+{y?|MI+^L{&@-h6u2O4fZn>t1*6-}V1r&vV^s6R=h3WL!XN7+4@# zDKN0AFb$GipN*gf$&RB2s{&mS3=b|jfopAIPjnYq^w4~HTkCBLxL9Oeqq2D@#is4z z@KG?>#5P?sXR`@z3=ms$sKEx||gYRtb6R=Rqt`!RzFtL3Y2Lr#S?GZXt6 z+Q9)ug$X%mIvN@&JvYV{Bh=sV5+)x<)l3HLSzO_sw(j$k%GHeUxuE>syy5LTPgHN$ z^Oj+pOY}(3rUB7WEN!Y2h0WZ9u9J5Y9QS;;JWmdj3;-A+;e~anf;TUYWwT4=Wrc8Pi|q2?T{EE-V2N&{Ag2i?_9d2lB#$TvYo*r>i|jBB#%M z!BZ!vmmQG@38YDp=`kIkt;JmDi4w*BxQeBU7aK?L+kc|h%(f`maAh%7P1$dLzD7TC z&fUW{becGkQW8COVyXXRI0^rtZQMB2?slEDl^*{x3d>6l#Hb|ioxe^8(cnj0Uf!i1 zQQ2uarh5t!DzQ6I5^xmBEFAi_!Wj#=?Kv>-cBIxxJyODTW&x0ph6Kzr6>53#(+f;_ zP0)IS!5{o~nAK8@FsEMrRzIy~XD?$lWCXo)XK<%Bk}1WSJ#Y2Y3jk&DM!*Dy9a8s7VZ(4jO*Kyxc@6RK+&_s8;aO+2r9y$r(Bvn>5NKQmpnVYRd zTSlUwqdteVT#7J4zFU^gBNUyUxF;0A5!7%0XV6V%w!VwSa~%oghn*_#2hA*Pj^8E4 zAK3Qo#Nds%&A1637h(0|^>?AmDMLO$@BuwS{1(HR;;7qSw@iw@gC8k4CDMy16|MXX zQ@*#`l6`U6sMF^t+8mHt9HnNAU9MwfY)LBnlCsNfO@Qi0<6qwDsYQR9%^dVINk1)w z!|1vDcnJh;rtvffo*T}azUjuj6Ky(gQ;V3ZAC{aNeses5XPkf8I}Eu9m7ynvX(rkC zQH&%|#<+3L`udsdME(eSjo{+c+t$9#sDI8LaPgdlRReLDbe(`|yNJE*#g#XW_)JXp z_r+pj*&0J3C~$q+D~K#ojb*jl-jFyLWTWFol5u%o8Cx1D!QKG{rYNIcrtoo@-gWTU1AvA`N>6Wt z^e*r-tf_hn>xog7ke_2{46%`(rd#MTt}7rtcBOZ3_=zteeBS!Lc= z%3`*Qc8X(qN}0`N?Q$V+5x`r0cNrs2xep~aeEu2}mJ1eS%I1~%x*ahY9F&=_6A*2% zVO#Pz$Er6&;ArU39gZ3F^A5Ad1i-XhJwO{mu;b6rVq&r-Pkd3dCgbj^Wlfv@B=l!_ zA%r%xV6X#fNQkw(xHEewcj?0ZL)7k;RKyLAy<(zhUqPVIrq#28XNKz!dPj!VN(C?t zW#^xCk1x*u>S1R*NA7*fim#6tzJlP7X!LmMw4;w^CE+UB!IF~~g0m*|vW2n*v7EK2 z?zc%;tzx2epTk^X2B+#bpKFagv8#w38=&&z6YWwEW0_z_qhD`ZAf_I%hPM@!Njv92 zC$T!Ut={v<__bFAu*bXh4DO_ax4Pp-(#hQ?;~%Zko1NrN`@Aq7_Kthd^hlL%HX?F? zFJ@JR)m!^OpcZmSRI68E>|GZsuTryfc9}a#U{cRR$SouIomDH6jEjlNB^1F3e(6Hr zr#E?H4ie+DN0?f+i)Jhw8|w{oqtwbG?>H~o$*R@Cs-%=0;-1^Ljbv%X8Y&ad%rTE^Z%PEvqCGgQ7-b{gO z#x*5DqMc~HAmQFA3Dy0q&y|kzKSO4+K!0P(pKDC>=gxQejQLBvm^!e0G*F^ghH1Iu`Q4I7lZ zlWnS4Kj+%l$lJ{;h#Wsi7?dMdM0Y$ad||&~hw?Q69Yp;8tO#=euQc5D-;%^8d3cqp zWC)3^uBrY#Q8&NsQ0V_;*WFxdjZH8l8H?KErkf|rR~FbD2OOG`?ity9$)h7*JArvb z-;NRp`xoJW`Boa*X_pvJ)f}eSFgZ!(t&XK}IL-V5V!+&6% zd*h?5Z^3|35G~F9R5?0UnrB))Kb~f3f>p=kuX?zUJR zn$AMPiPBwvg@f!8APr5G`rz-p!NlpMtnBe_w=MZ(Wbc@0QH(pXY`ZuzzaSr~Mcyk5 zJlo0uQMQsnXNL%5Ny8*YYA%q%38ZN!RzLkBRoB>Dp+^U+NY>U-nONAbERRETaAcuJ zzgK4=b-B3wc&WL|GgUTV`(k5aCyn~sCpB|T*_=#4M?=*qcBj@s<3gGwQc6K%WJ9?y zqO6T?m*{$!gFNHKU7_CJ6Heh@l@`z9WtR&3EpBC%l)@tF#(k`gtlZxhP5dNC=&P2> zlbTpoR-IvowtDai#66KQ7bnrok_N95tg9qiFI?Q}r#%(|hV6OtvP36?tTm)0{Th{i zdTu)uuuFT(jy3Zm;T5>X5;b&xbCub_j@mTzt*{;RKAFzqx!q`|ILflu7Ei zs)R`9{+&$7&ls0U5wT7_{$>CgRTG})ymR6$3K~Tq#VTP>EQhCC)nz{#trST{@s}?( zR-4VGc7RfLXL@d$h02I@4YC!~y0Lg!K(_v+Jw7}_ znhG~(h!Ee2yHfFrtv-X<*Ott|>Z0V$Rb`>WEK8<`0QJnoBMl9g`1H^_St4EmT(X7Z z7U~Z0vR8xm0Vc)Y!6FD3{Mq9BL_JT{Dgm%mB3;ROxEOo0+3L3QYMLeG;h4wW)3hss zd);X-bzLaKfJPuim&#zy4|URvvk}$exv+xFEGi%kto7{UrtKh&qPh9PzL+KtmrZ!O z2L5dtI!9$Xu0iRQYXf;9ZO1W^cbkCla7lIFYj39ZNNI)p_Dm@l;P9&|gsb*a-Z2D! zm(b`8ne2f*;qdD?J~qKYh$P9@eBV+6DK!3bp>eJ}ViyD9j+D4Tq_xc}R_XhC;*(?w ze7vwv6Dk+h9O!csxAUhjrD6qGa2!TZa+*2FKl{=-7F{#uHT4(M zhuS`!$EsnWEKhAPDeruGhHo`@V82{u^byVt>qtamKA1At>q6CxdC^TO@PZnV=Rt^~ zjH%3=XgRsDj3x$2nR2n$B%S>Fq}QY|h-0=swf$7^tLTk8FuwB=%QgZG{PaIsh>@^g0ezVd=Mju3dU@%iaM{ z5xkfp6waZl7`cQjtANRTrp*yu<^f!7yQkDO3Qs3rvmYLPoipnAc>O``PT-#t&`wYr zBjdU8v#sNo$jAUm_K&9#w;VXwVR$y8H-FOlGLLmvL)dE2E9H=!+Jg-QJQ_}K9i?;c zYU8wn7)hKR-eyQ}1!{bZnw~aq+;h3fDwFZYLfn-Js~5I&H)&ZvU197?+T7rV$=$Qm z;RlP)o}k7Tr4o2zbL$5v1%FJ3zE(}E)Fw|vGPjhy#asAXNr2dKhR{*pJV7%((@}ne z5H-hx2$XEkrTNs5^n19Ze$l5!bI_5Q>nzF#;u8Fhs=Io6P5RkrpjN9fSJHbi=jxqC z%eMW5od(Y(NXna3%zHIISA5VbNl7i+a(9H*dUxDN$;F2Qu2YSY(*Yg~fSX7w+Q-~< zyN^gL<-Cb*LEWVLpd13TCh6C}MyHCFuM>Y9LziPWxq$U8pmkg$<;RXlu%R6)=GKkH zo7KG6xTbByR8d4KdAyBt{MZa1>*S={32*vgF;B!Sq%rc_Gs+%bgQcm}83pWaTiGyg z!~RXXz{%FKj}f`wj9N|dp4@=>HEZmq7sQX{P(<-c*~>_dq}2%_xS0bs7TfMJlq>Xr z(|s(cEz-5eE5wHs)%{V4rD-9@aJI=%{iKzp0YCSmda8Oi@(1AF5Y}`m3iOurvupiM z75%>=^FK5t6-e)C*{G{J$8B zO>1o#-PUs00$-dymtAng9jrZSqnyT5wtGXuz|XfV8^ZAMdLto$>*zcmy zv~KXlH@%U9O|#{;99~>AcrnY;Fy|?HVO%SPwWuk()S%S+S$&T=71vcfxx&AKPA}~a z#MM~F%Ep45`*V^PtYh~`1w}=q+oC*^F_GP2Wf}f_h#UQucF2jtnyfBe*KP$4TJbWxIPn+a!2v}xslM?EayDi+-7K+}sEiRlwBy>*g~e8O zgi3kbj69EfiApzMmtarleY{Z(ZiVldN)$Y%oBpn{_cjN;2Me7ze024y^^W1XqcF2D zUN<>dJlDlz2^6eaD9GvDmnE%$TRsceKMxA94%KpzGqfEOVG2*5-8RufcQ=PhFkf-h zvky8t5k|~MGuw$)!u_u~Zwl>%*crbD``B@h4V*SGOe-T6NucKlXyr(-dU#&Lh&Uz3 zl4m}>3W@kB^Cfj-Mm7)|_)vl`HWUAm}ynYb@$2`7#j;F@Z+lH)Uf zvJn+ZK$5q72rmDJD6AzQ&Y(ZyP@l&hWEM5poaC63%it~j{6#AsBa+1iHNHi-968&M zPn&|iW!iU#Hxzk4x@dqjG}?5YIAyE&@Xd`Z7*4{S+}b*dx@l;bkM$otu-wn)1hVU` z`>|S=*6yE&f2crpGDY}_&F0J9pNdbZ<$ep4wz_Chq1$s~f@ED%)0pW|Tv_RvGADnv zY(p8Nxt%;b_LD972;suh%gQ@#%I9t2sHo$b?sr zkY%DdXK=~qWxV8+D0XOY`9b=pDHJ70Uq53h74qkm>WOmGk}%*a*+{*X1neQF+BshF z7nX7WLDfDKVXC~l4+>M*5=Yq*rYZ!KZHav$uOPsL8>bS39KNyNvu`<%bZE9+_8yFC zt6l9WeJ?%}pjEX{J2Y-b*TzmiiJi=zHT9)-KG*={k%C)uCyQ9$6;!dC&l8G+4!KUh z@W1KH{h0C2ZK*MefiFG5r{ zLojMhi_FR&kVHUK93i@l7{@$u*RItC-m@+dod?}1Wi zPP_zo9K^EDvl(BTA}E7R{_h3PZ+o*`)+Ie$ec?cZ>Kn49{Z=O!t8_kc*;)|QyyRPw z_oqrCmv>&?L4Lu72m|yC$E$A!?xHzORmDgp!z|=jpN{mcVx+FQ+4~=KG=Hz(`8_1G z<41wx=DL<64!polBsA+0U%x4Zf+C7@j*%4nVrm_jVs?T3nmV?Cq7cXhgnojU%@wND zdUl0MzV_#Uo>#RhW5dNitL{qln{%siqf6qsZtA+3zQ!1}`erVNDX@i5;b2EKW&b|5 zm;^)@@@aufdwpCZ>Gv3_|N`}RBwlcRmiirDg8C~E>EX<*b54W9NphCRHS5I z;bra05}bYj@5t#m3F_^w-y0}7pMANw5(7&lFgzX@YVemYdD87V@Gb#{dQ9k?a;onH zS@*Pk)nKYiz$GDNHZhcL(nLXyCN$d0y| zTv$I<&nN|p!w)m54?34qmkq=~5;o$=-~ayUJv=FKu>X@jYHT{H5};7|?!z?({4~|x z#xmpyk<#KwGkZo82BMQ3dl1p%Pg^z^)0G zz9V(7o%?{)q5}qf_rAYkJ1B8L;)?q-$I62Ftic<7Uc$+~0=W-M&K<_KV&YVUgpGKZ z!+}D|+Um_pYyLefy3M}Llrq`;43PzBj4A4}EEgD6TQ}!zYq&e(YuK$o&50AfXwTac z4})O&Hnc;UVD|oe%!qd%&k&zz<*s-^yvtWx&|(~N=S>P(o2o5(m-D2{$crqIOMH_W z_iw<#X@hS5V(<3iB_erQg<+hhPMem5YKyn$4aR!~FB896)XC;X7u}I~7*F>5_MSk5 z9yQU@TNmC=?LZYLN2&?l#a+Dkxej-GH87WPq`$5cU^4Npn;+1cT; z#YC%98$S&{OLgWmF7Huws+*57eY{|ZT>EmlK`Z<^+o_}WDv#>g`n105c3bp+}-_7;dz-od<&sQmcdiqU{!F z@bm5#r5IcMV@bUna3eqdUR1s0TuLDR(Eh1GkMj31X~ve@6H1WqosoyWbn?k4@y`v) zYo1p-{;YcD;^D7p%+KZfiS?;K)U*a0@VLQ(>JGbvPDw{ie~2uwvSu6Y)&<{a_wP2* zDBY5krP1T~Ef0PR2AAa7HP1Yc#eWsVVJBNyxxB)ikx8Yk#$}Xtugd9-Z5C?+3iz-oCIE#v7uiYV{Ag^Y(xm zWgS{7of&K#RC&w*zHrL)ce{|Kp~9jH2xFVPa!Q9Y^Fs}#qmj*!)MbC(uNyoE4FlbW@-K&6 zO2k|%RT17QoN>Kn70=YhYO_p=oo}vmX?zSqVzWrExD=1$#rxm1P}9VmLX!ryUP)~X zZC~p(lYxeViBr{H4FLQs=evp&v`%Tw&E#{{Tl!-N=iooO+*RM z`;KdWGM0ty)5#?%1-E^pTfLVIa(ldh{XG4@i?Y9f?|6PMf13ZMI!pb<|3yhtzxhwo z_y1ku{hvXoGeGlS%ijMpC;va@#Ppe`iplRlG)Eumo?h^SKBkG7q}cwu(d+9NKdRJz H@z4JP4@+@R literal 0 HcmV?d00001 diff --git a/src/reactlogo.svg b/src/assets/reactlogo.svg similarity index 100% rename from src/reactlogo.svg rename to src/assets/reactlogo.svg From 8d22414e198076d503dbf410085a749f23eb5bf2 Mon Sep 17 00:00:00 2001 From: E-Liang Tan Date: Tue, 28 Jul 2020 17:59:35 +0800 Subject: [PATCH 052/116] Fix lint failure from #88 --- src/ImportPage.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ImportPage.js b/src/ImportPage.js index 8c10952923193..e67e42733cd11 100644 --- a/src/ImportPage.js +++ b/src/ImportPage.js @@ -81,7 +81,8 @@ export default function ImportPage({onDataImported}: Props) { {' '} from Chrome Devtools.
- To zoom, scroll while holding down Ctrl or Shift + To zoom, scroll while holding down Ctrl or{' '} + Shift