UNPKG

set-state-compare

Version:

setState for React that compares with the current state and only sets the state if changed.

271 lines 31.8 kB
import { arrayReferenceDifferent, referenceDifferent } from "./diff-utils.js"; import { dig } from "diggerize"; import fetchingObject from "fetching-object"; import memoCompareProps from "./memo-compare-props.js"; import PropTypes from "prop-types"; import shared from "./shared.js"; import { useEffect, useMemo, useState } from "react"; /** * @typedef {object} ShapeLifecycleHooks * @property {(prevProps: Record<string, any>, prevState: Record<string, any>) => void} [componentDidUpdate] * @property {() => void} [componentDidMount] * @property {() => void} [componentWillUnmount] * @property {{children: [import("react").ReactNode]}} props * @property {() => void} [setup] */ class ShapeComponent { /** @type {Record<string, any> | undefined} */ static defaultProps = undefined; /** @type {Record<string, import("prop-types").Validator>} */ static propTypes = undefined; /** @type {Record<string, {dependencies?: any[], value: any}> | undefined} */ static __staticCaches = undefined; /** * @param {Record<string, any>} props */ constructor(props) { this.__caches = {}; this.__mounting = true; this.__mounted = false; this.props = props; this.setStates = {}; this.state = {}; this.__firstRenderCompleted = false; this.tt = fetchingObject(this); this.p = fetchingObject(() => this.props); this.s = fetchingObject(this.state); } /** * @template T * @param {string} name * @param {T | (() => T)} value * @param {any[]} [dependencies] * @returns {T} */ cache(name, value, dependencies) { let actualValue; const oldDependencies = this.__caches[name]?.dependencies; if (typeof value == "function") { // @ts-expect-error actualValue = value(); } else { actualValue = value; } if (!(name in this.__caches) || arrayReferenceDifferent(oldDependencies || [], dependencies || [])) { this.__caches[name] = { dependencies, value: actualValue }; } return this.__caches[name].value; } /** * @template T * @param {string} name * @param {T | (() => T)} value * @param {any[]} [dependencies] * @returns {T} */ cacheStatic(name, value, dependencies) { const constructor = /** @type {typeof ShapeComponent} */ (this.constructor); if (!constructor.__staticCaches) { constructor.__staticCaches = {}; } const oldDependencies = constructor.__staticCaches[name]?.dependencies; const hasCache = name in constructor.__staticCaches; const depsChanged = arrayReferenceDifferent(oldDependencies || [], dependencies || []); if (!hasCache || depsChanged) { let actualValue; if (typeof value == "function") { // @ts-expect-error actualValue = value(); } else { actualValue = value; } constructor.__staticCaches[name] = { dependencies, value: actualValue }; } return constructor.__staticCaches[name].value; } /** * @param {Record<string, any>} variables * @returns {void} */ setInstance(variables) { for (const name in variables) { this[name] = variables[name]; } } /** * @param {Record<string, any>} statesList * @param {function() : void} [callback] * @returns {void} */ setState(statesList, callback) { if (typeof statesList == "function") { statesList = statesList(this.state); } for (const stateName in statesList) { const newValue = statesList[stateName]; if (!(stateName in this.setStates)) { throw new Error(`No such state: ${stateName}`); } this.setStates[stateName](newValue); } if (callback) { shared.enqueueRenderCallback(callback); } } /** * @param {Record<string, any>} statesList * @returns {Promise<void>} */ setStateAsync(statesList) { return new Promise((resolve) => { this.setState(statesList, resolve); }); } /** * @param {string} stylingName * @param {Record<string, any>} style * @returns {Record<string, any>} */ stylingFor(stylingName, style = {}) { let customStyling = dig(this, "props", "styles", stylingName); if (typeof customStyling == "function") { customStyling = customStyling({ state: this.state, style }); } if (customStyling) { return Object.assign(style, customStyling); } return style; } /** * @param {string} stateName * @param {any} defaultValue * @returns {any} */ useState(stateName, defaultValue) { const [stateValue, setState] = useState(defaultValue); if (!(stateName in this.state)) { this.state[stateName] = stateValue; this.setStates[stateName] = (newValue, args) => { if (referenceDifferent(this.state[stateName], newValue)) { let prevState; // @ts-expect-error if (this.componentDidUpdate) { prevState = Object.assign({}, this.state); } this.state[stateName] = newValue; // Avoid React error if using set-state while rendering (like in a useMemo callback) if (!args?.silent) { if (shared.rendering > 0) { shared.enqueueRenderCallback(() => setState(newValue)); } else { setState(newValue); } } // @ts-expect-error if (this.componentDidUpdate) { // @ts-expect-error this.componentDidUpdate(this.props, prevState); } } }; } return this.setStates[stateName]; } /** * @param {Array<string>|Record<string, any>} statesList * @returns {void} */ useStates(statesList) { if (Array.isArray(statesList)) { for (const stateName of statesList) { this.useState(stateName); } } else { for (const stateName in statesList) { const defaultValue = statesList[stateName]; this.useState(stateName, defaultValue); } } } } /** * @param {typeof ShapeComponent} ShapeClass * @returns {function(Record<string, any>): import("react").ReactNode} React functional component that renders the ShapeClass */ const shapeComponent = (ShapeClass) => { /** * @param {Record<string, any>} props * @returns {import("react").ReactNode} React element that renders the ShapeClass */ const functionalComponent = (props) => { // Count rendering to avoid setting state while rendering which causes a console-error from React shared.rendering += 1; try { // Calculate and validate props let actualProps; if (ShapeClass.defaultProps) { // Undefined values are removed from the props because they shouldn't override default values const propsWithoutUndefined = Object.assign({}, props); for (const key in propsWithoutUndefined) { const value = propsWithoutUndefined[key]; if (value === undefined) { delete propsWithoutUndefined[key]; } } actualProps = Object.assign({}, ShapeClass.defaultProps, propsWithoutUndefined); } else { actualProps = props; } if (ShapeClass.propTypes) { const validateProps = {}; for (const key in actualProps) { // Accessing 'key' will result in a warning in the console if (key == "key") continue; validateProps[key] = actualProps[key]; } PropTypes.checkPropTypes(ShapeClass.propTypes, validateProps, "prop", ShapeClass.name); } const shape = useMemo(() => new ShapeClass(actualProps), []); const prevProps = shape.props; shape.props = actualProps; if (shape.setup) { shape.setup(); } if (shape.componentDidUpdate && shape.__firstRenderCompleted && memoCompareProps(shape.props, props)) { shape.componentDidUpdate(prevProps, shape.state); } useEffect(() => { shape.__mounting = false; shape.__mounted = true; if (shape.componentDidMount) { shape.componentDidMount(); } return () => { shape.__mounted = false; if (shape.componentWillUnmount) { shape.componentWillUnmount(); } }; }, []); shape.__firstRenderCompleted = true; // Finally render the component and return it return shape.render(); } finally { shared.scheduleAfterPaint(() => { shared.rendering = Math.max(0, shared.rendering - 1); }); } }; functionalComponent.displayName = ShapeClass.name; Object.defineProperty(functionalComponent, "name", { value: ShapeClass.name }); return functionalComponent; }; export { shapeComponent, ShapeComponent }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2hhcGUtY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3NoYXBlLWNvbXBvbmVudC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUMsdUJBQXVCLEVBQUUsa0JBQWtCLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQTtBQUMzRSxPQUFPLEVBQUMsR0FBRyxFQUFDLE1BQU0sV0FBVyxDQUFBO0FBQzdCLE9BQU8sY0FBYyxNQUFNLGlCQUFpQixDQUFBO0FBQzVDLE9BQU8sZ0JBQWdCLE1BQU0seUJBQXlCLENBQUE7QUFDdEQsT0FBTyxTQUFTLE1BQU0sWUFBWSxDQUFBO0FBQ2xDLE9BQU8sTUFBTSxNQUFNLGFBQWEsQ0FBQTtBQUNoQyxPQUFPLEVBQUMsU0FBUyxFQUFFLE9BQU8sRUFBRSxRQUFRLEVBQUMsTUFBTSxPQUFPLENBQUE7QUFFbEQ7Ozs7Ozs7R0FPRztBQUVILE1BQU0sY0FBYztJQUNsQiw4Q0FBOEM7SUFDOUMsTUFBTSxDQUFDLFlBQVksR0FBRyxTQUFTLENBQUE7SUFFL0IsNkRBQTZEO0lBQzdELE1BQU0sQ0FBQyxTQUFTLEdBQUcsU0FBUyxDQUFBO0lBRTVCLDZFQUE2RTtJQUM3RSxNQUFNLENBQUMsY0FBYyxHQUFHLFNBQVMsQ0FBQTtJQUVqQzs7T0FFRztJQUNILFlBQVksS0FBSztRQUNmLElBQUksQ0FBQyxRQUFRLEdBQUcsRUFBRSxDQUFBO1FBQ2xCLElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFBO1FBQ3RCLElBQUksQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFBO1FBQ3RCLElBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFBO1FBQ2xCLElBQUksQ0FBQyxTQUFTLEdBQUcsRUFBRSxDQUFBO1FBQ25CLElBQUksQ0FBQyxLQUFLLEdBQUcsRUFBRSxDQUFBO1FBQ2YsSUFBSSxDQUFDLHNCQUFzQixHQUFHLEtBQUssQ0FBQTtRQUNuQyxJQUFJLENBQUMsRUFBRSxHQUFHLGNBQWMsQ0FB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QUssRUFBRSxVQUFVLENBQUMsSUFBSSxFQUFDLENBQUMsQ0FBQTtJQUU1RSxPQUFPLG1CQUFtQixDQUFBO0FBQzVCLENBQUMsQ0FBQTtBQUVELE9BQU8sRUFBQyxjQUFjLEVBQUUsY0FBYyxFQUFDLENBQUEiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge2FycmF5UmVmZXJlbmNlRGlmZmVyZW50LCByZWZlcmVuY2VEaWZmZXJlbnR9IGZyb20gXCIuL2RpZmYtdXRpbHMuanNcIlxuaW1wb3J0IHtkaWd9IGZyb20gXCJkaWdnZXJpemVcIlxuaW1wb3J0IGZldGNoaW5nT2JqZWN0IGZyb20gXCJmZXRjaGluZy1vYmplY3RcIlxuaW1wb3J0IG1lbW9Db21wYXJlUHJvcHMgZnJvbSBcIi4vbWVtby1jb21wYXJlLXByb3BzLmpzXCJcbmltcG9ydCBQcm9wVHlwZXMgZnJvbSBcInByb3AtdHlwZXNcIlxuaW1wb3J0IHNoYXJlZCBmcm9tIFwiLi9zaGFyZWQuanNcIlxuaW1wb3J0IHt1c2VFZmZlY3QsIHVzZU1lbW8sIHVzZVN0YXRlfSBmcm9tIFwicmVhY3RcIlxuXG4vKipcbiAqIEB0eXBlZGVmIHtvYmplY3R9IFNoYXBlTGlmZWN5Y2xlSG9va3NcbiAqIEBwcm9wZXJ0eSB7KHByZXZQcm9wczogUmVjb3JkPHN0cmluZywgYW55PiwgcHJldlN0YXRlOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KSA9PiB2b2lkfSBbY29tcG9uZW50RGlkVXBkYXRlXVxuICogQHByb3BlcnR5IHsoKSA9PiB2b2lkfSBbY29tcG9uZW50RGlkTW91bnRdXG4gKiBAcHJvcGVydHkgeygpID0+IHZvaWR9IFtjb21wb25lbnRXaWxsVW5tb3VudF1cbiAqIEBwcm9wZXJ0eSB7e2NoaWxkcmVuOiBbaW1wb3J0KFwicmVhY3RcIikuUmVhY3ROb2RlXX19IHByb3BzXG4gKiBAcHJvcGVydHkgeygpID0+IHZvaWR9IFtzZXR1cF1cbiAqL1xuXG5jbGFzcyBTaGFwZUNvbXBvbmVudCB7XG4gIC8qKiBAdHlwZSB7UmVjb3JkPHN0cmluZywgYW55PiB8IHVuZGVmaW5lZH0gKi9cbiAgc3RhdGljIGRlZmF1bHRQcm9wcyA9IHVuZGVmaW5lZFxuXG4gIC8qKiBAdHlwZSB7UmVjb3JkPHN0cmluZywgaW1wb3J0KFwicHJvcC10eXBlc1wiKS5WYWxpZGF0b3I+fSAqL1xuICBzdGF0aWMgcHJvcFR5cGVzID0gdW5kZWZpbmVkXG5cbiAgLyoqIEB0eXBlIHtSZWNvcmQ8c3RyaW5nLCB7ZGVwZW5kZW5jaWVzPzogYW55W10sIHZhbHVlOiBhbnl9PiB8IHVuZGVmaW5lZH0gKi9cbiAgc3RhdGljIF9fc3RhdGljQ2FjaGVzID0gdW5kZWZpbmVkXG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgYW55Pn0gcHJvcHNcbiAgICovXG4gIGNvbnN0cnVjdG9yKHByb3BzKSB7XG4gICAgdGhpcy5fX2NhY2hlcyA9IHt9XG4gICAgdGhpcy5fX21vdW50aW5nID0gdHJ1ZVxuICAgIHRoaXMuX19tb3VudGVkID0gZmFsc2VcbiAgICB0aGlzLnByb3BzID0gcHJvcHNcbiAgICB0aGlzLnNldFN0YXRlcyA9IHt9XG4gICAgdGhpcy5zdGF0ZSA9IHt9XG4gICAgdGhpcy5fX2ZpcnN0UmVuZGVyQ29tcGxldGVkID0gZmFsc2VcbiAgICB0aGlzLnR0ID0gZmV0Y2hpbmdPYmplY3QodGhpcylcbiAgICB0aGlzLnAgPSBmZXRjaGluZ09iamVjdCgoKSA9PiB0aGlzLnByb3BzKVxuICAgIHRoaXMucyA9IGZldGNoaW5nT2JqZWN0KHRoaXMuc3RhdGUpXG4gIH1cblxuICAvKipcbiAgICogQHRlbXBsYXRlIFRcbiAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAgICogQHBhcmFtIHtUIHwgKCgpID0+IFQpfSB2YWx1ZVxuICAgKiBAcGFyYW0ge2FueVtdfSBbZGVwZW5kZW5jaWVzXVxuICAgKiBAcmV0dXJucyB7VH1cbiAgICovXG4gIGNhY2hlKG5hbWUsIHZhbHVlLCBkZXBlbmRlbmNpZXMpIHtcbiAgICBsZXQgYWN0dWFsVmFsdWVcbiAgICBjb25zdCBvbGREZXBlbmRlbmNpZXMgPSB0aGlzLl9fY2FjaGVzW25hbWVdPy5kZXBlbmRlbmNpZXNcblxuICAgIGlmICh0eXBlb2YgdmFsdWUgPT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAvLyBAdHMtZXhwZWN0LWVycm9yXG4gICAgICBhY3R1YWxWYWx1ZSA9IHZhbHVlKClcbiAgICB9IGVsc2Uge1xuICAgICAgYWN0dWFsVmFsdWUgPSB2YWx1ZVxuICAgIH1cblxuICAgIGlmICghKG5hbWUgaW4gdGhpcy5fX2NhY2hlcykgfHwgYXJyYXlSZWZlcmVuY2VEaWZmZXJlbnQob2xkRGVwZW5kZW5jaWVzIHx8IFtdLCBkZXBlbmRlbmNpZXMgfHwgW10pKSB7XG4gICAgICB0aGlzLl9fY2FjaGVzW25hbWVdID0ge2RlcGVuZGVuY2llcywgdmFsdWU6IGFjdHVhbFZhbHVlfVxuICAgIH1cblxuICAgIHJldHVybiB0aGlzLl9fY2FjaGVzW25hbWVdLnZhbHVlXG4gIH1cblxuICAvKipcbiAgICogQHRlbXBsYXRlIFRcbiAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAgICogQHBhcmFtIHtUIHwgKCgpID0+IFQpfSB2YWx1ZVxuICAgKiBAcGFyYW0ge2FueVtdfSBbZGVwZW5kZW5jaWVzXVxuICAgKiBAcmV0dXJucyB7VH1cbiAgICovXG4gIGNhY2hlU3RhdGljKG5hbWUsIHZhbHVlLCBkZXBlbmRlbmNpZXMpIHtcbiAgICBjb25zdCBjb25zdHJ1Y3RvciA9IC8qKiBAdHlwZSB7dHlwZW9mIFNoYXBlQ29tcG9uZW50fSAqLyAodGhpcy5jb25zdHJ1Y3RvcilcblxuICAgIGlmICghY29uc3RydWN0b3IuX19zdGF0aWNDYWNoZXMpIHtcbiAgICAgIGNvbnN0cnVjdG9yLl9fc3RhdGljQ2FjaGVzID0ge31cbiAgICB9XG5cbiAgICBjb25zdCBvbGREZXBlbmRlbmNpZXMgPSBjb25zdHJ1Y3Rvci5fX3N0YXRpY0NhY2hlc1tuYW1lXT8uZGVwZW5kZW5jaWVzXG5cbiAgICBjb25zdCBoYXNDYWNoZSA9IG5hbWUgaW4gY29uc3RydWN0b3IuX19zdGF0aWNDYWNoZXNcbiAgICBjb25zdCBkZXBzQ2hhbmdlZCA9IGFycmF5UmVmZXJlbmNlRGlmZmVyZW50KG9sZERlcGVuZGVuY2llcyB8fCBbXSwgZGVwZW5kZW5jaWVzIHx8IFtdKVxuXG4gICAgaWYgKCFoYXNDYWNoZSB8fCBkZXBzQ2hhbmdlZCkge1xuICAgICAgbGV0IGFjdHVhbFZhbHVlXG5cbiAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3JcbiAgICAgICAgYWN0dWFsVmFsdWUgPSB2YWx1ZSgpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBhY3R1YWxWYWx1ZSA9IHZhbHVlXG4gICAgICB9XG5cbiAgICAgIGNvbnN0cnVjdG9yLl9fc3RhdGljQ2FjaGVzW25hbWVdID0ge2RlcGVuZGVuY2llcywgdmFsdWU6IGFjdHVhbFZhbHVlfVxuICAgIH1cblxuICAgIHJldHVybiBjb25zdHJ1Y3Rvci5fX3N0YXRpY0NhY2hlc1tuYW1lXS52YWx1ZVxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgYW55Pn0gdmFyaWFibGVzXG4gICAqIEByZXR1cm5zIHt2b2lkfVxuICAgKi9cbiAgc2V0SW5zdGFuY2UodmFyaWFibGVzKSB7XG4gICAgZm9yIChjb25zdCBuYW1lIGluIHZhcmlhYmxlcykge1xuICAgICAgdGhpc1tuYW1lXSA9IHZhcmlhYmxlc1tuYW1lXVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIGFueT59IHN0YXRlc0xpc3RcbiAgICogQHBhcmFtIHtmdW5jdGlvbigpIDogdm9pZH0gW2NhbGxiYWNrXVxuICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICovXG4gIHNldFN0YXRlKHN0YXRlc0xpc3QsIGNhbGxiYWNrKSB7XG4gICAgaWYgKHR5cGVvZiBzdGF0ZXNMaXN0ID09IFwiZnVuY3Rpb25cIikge1xuICAgICAgc3RhdGVzTGlzdCA9IHN0YXRlc0xpc3QodGhpcy5zdGF0ZSlcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IHN0YXRlTmFtZSBpbiBzdGF0ZXNMaXN0KSB7XG4gICAgICBjb25zdCBuZXdWYWx1ZSA9IHN0YXRlc0xpc3Rbc3RhdGVOYW1lXVxuXG4gICAgICBpZiAoIShzdGF0ZU5hbWUgaW4gdGhpcy5zZXRTdGF0ZXMpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgTm8gc3VjaCBzdGF0ZTogJHtzdGF0ZU5hbWV9YClcbiAgICAgIH1cblxuICAgICAgdGhpcy5zZXRTdGF0ZXNbc3RhdGVOYW1lXShuZXdWYWx1ZSlcbiAgICB9XG5cbiAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgIHNoYXJlZC5lbnF1ZXVlUmVuZGVyQ2FsbGJhY2soY2FsbGJhY2spXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgYW55Pn0gc3RhdGVzTGlzdFxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn1cbiAgICovXG4gIHNldFN0YXRlQXN5bmMoc3RhdGVzTGlzdCkge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xuICAgICAgdGhpcy5zZXRTdGF0ZShzdGF0ZXNMaXN0LCByZXNvbHZlKVxuICAgIH0pXG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtzdHJpbmd9IHN0eWxpbmdOYW1lXG4gICAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgYW55Pn0gc3R5bGVcbiAgICogQHJldHVybnMge1JlY29yZDxzdHJpbmcsIGFueT59XG4gICAqL1xuICBzdHlsaW5nRm9yKHN0eWxpbmdOYW1lLCBzdHlsZSA9IHt9KSB7XG4gICAgbGV0IGN1c3RvbVN0eWxpbmcgPSBkaWcodGhpcywgXCJwcm9wc1wiLCBcInN0eWxlc1wiLCBzdHlsaW5nTmFtZSlcblxuICAgIGlmICh0eXBlb2YgY3VzdG9tU3R5bGluZyA9PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgIGN1c3RvbVN0eWxpbmcgPSBjdXN0b21TdHlsaW5nKHtzdGF0ZTogdGhpcy5zdGF0ZSwgc3R5bGV9KVxuICAgIH1cblxuICAgIGlmIChjdXN0b21TdHlsaW5nKSB7XG4gICAgICByZXR1cm4gT2JqZWN0LmFzc2lnbihzdHlsZSwgY3VzdG9tU3R5bGluZylcbiAgICB9XG5cbiAgICByZXR1cm4gc3R5bGVcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RhdGVOYW1lXG4gICAqIEBwYXJhbSB7YW55fSBkZWZhdWx0VmFsdWVcbiAgICogQHJldHVybnMge2FueX1cbiAgICovXG4gIHVzZVN0YXRlKHN0YXRlTmFtZSwgZGVmYXVsdFZhbHVlKSB7XG4gICAgY29uc3QgW3N0YXRlVmFsdWUsIHNldFN0YXRlXSA9IHVzZVN0YXRlKGRlZmF1bHRWYWx1ZSlcblxuICAgIGlmICghKHN0YXRlTmFtZSBpbiB0aGlzLnN0YXRlKSkge1xuICAgICAgdGhpcy5zdGF0ZVtzdGF0ZU5hbWVdID0gc3RhdGVWYWx1ZVxuICAgICAgdGhpcy5zZXRTdGF0ZXNbc3RhdGVOYW1lXSA9IChuZXdWYWx1ZSwgYXJncykgPT4ge1xuICAgICAgICBpZiAocmVmZXJlbmNlRGlmZmVyZW50KHRoaXMuc3RhdGVbc3RhdGVOYW1lXSwgbmV3VmFsdWUpKSB7XG4gICAgICAgICAgbGV0IHByZXZTdGF0ZVxuXG4gICAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvclxuICAgICAgICAgIGlmICh0aGlzLmNvbXBvbmVudERpZFVwZGF0ZSkge1xuICAgICAgICAgICAgcHJldlN0YXRlID0gT2JqZWN0LmFzc2lnbih7fSwgdGhpcy5zdGF0ZSlcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB0aGlzLnN0YXRlW3N0YXRlTmFtZV0gPSBuZXdWYWx1ZVxuXG4gICAgICAgICAgLy8gQXZvaWQgUmVhY3QgZXJyb3IgaWYgdXNpbmcgc2V0LXN0YXRlIHdoaWxlIHJlbmRlcmluZyAobGlrZSBpbiBhIHVzZU1lbW8gY2FsbGJhY2spXG4gICAgICAgICAgaWYgKCFhcmdzPy5zaWxlbnQpIHtcbiAgICAgICAgICAgIGlmIChzaGFyZWQucmVuZGVyaW5nID4gMCkge1xuICAgICAgICAgICAgICBzaGFyZWQuZW5xdWV1ZVJlbmRlckNhbGxiYWNrKCgpID0+IHNldFN0YXRlKG5ld1ZhbHVlKSlcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHNldFN0YXRlKG5ld1ZhbHVlKVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3JcbiAgICAgICAgICBpZiAodGhpcy5jb21wb25lbnREaWRVcGRhdGUpIHtcbiAgICAgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3JcbiAgICAgICAgICAgIHRoaXMuY29tcG9uZW50RGlkVXBkYXRlKHRoaXMucHJvcHMsIHByZXZTdGF0ZSlcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5zZXRTdGF0ZXNbc3RhdGVOYW1lXVxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7QXJyYXk8c3RyaW5nPnxSZWNvcmQ8c3RyaW5nLCBhbnk+fSBzdGF0ZXNMaXN0XG4gICAqIEByZXR1cm5zIHt2b2lkfVxuICAgKi9cbiAgdXNlU3RhdGVzKHN0YXRlc0xpc3QpIHtcbiAgICBpZiAoQXJyYXkuaXNBcnJheShzdGF0ZXNMaXN0KSkge1xuICAgICAgZm9yKGNvbnN0IHN0YXRlTmFtZSBvZiBzdGF0ZXNMaXN0KSB7XG4gICAgICAgIHRoaXMudXNlU3RhdGUoc3RhdGVOYW1lKVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBmb3IoY29uc3Qgc3RhdGVOYW1lIGluIHN0YXRlc0xpc3QpIHtcbiAgICAgICAgY29uc3QgZGVmYXVsdFZhbHVlID0gc3RhdGVzTGlzdFtzdGF0ZU5hbWVdXG5cbiAgICAgICAgdGhpcy51c2VTdGF0ZShzdGF0ZU5hbWUsIGRlZmF1bHRWYWx1ZSlcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBAcGFyYW0ge3R5cGVvZiBTaGFwZUNvbXBvbmVudH0gU2hhcGVDbGFzc1xuICogQHJldHVybnMge2Z1bmN0aW9uKFJlY29yZDxzdHJpbmcsIGFueT4pOiBpbXBvcnQoXCJyZWFjdFwiKS5SZWFjdE5vZGV9IFJlYWN0IGZ1bmN0aW9uYWwgY29tcG9uZW50IHRoYXQgcmVuZGVycyB0aGUgU2hhcGVDbGFzc1xuICovXG5jb25zdCBzaGFwZUNvbXBvbmVudCA9IChTaGFwZUNsYXNzKSA9PiB7XG4gIC8qKlxuICAgKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIGFueT59IHByb3BzXG4gICAqIEByZXR1cm5zIHtpbXBvcnQoXCJyZWFjdFwiKS5SZWFjdE5vZGV9IFJlYWN0IGVsZW1lbnQgdGhhdCByZW5kZXJzIHRoZSBTaGFwZUNsYXNzXG4gICAqL1xuICBjb25zdCBmdW5jdGlvbmFsQ29tcG9uZW50ID0gKHByb3BzKSA9PiB7XG4gICAgLy8gQ291bnQgcmVuZGVyaW5nIHRvIGF2b2lkIHNldHRpbmcgc3RhdGUgd2hpbGUgcmVuZGVyaW5nIHdoaWNoIGNhdXNlcyBhIGNvbnNvbGUtZXJyb3IgZnJvbSBSZWFjdFxuICAgIHNoYXJlZC5yZW5kZXJpbmcgKz0gMVxuXG4gICAgdHJ5IHtcbiAgICAgIC8vIENhbGN1bGF0ZSBhbmQgdmFsaWRhdGUgcHJvcHNcbiAgICAgIGxldCBhY3R1YWxQcm9wc1xuXG4gICAgICBpZiAoU2hhcGVDbGFzcy5kZWZhdWx0UHJvcHMpIHtcbiAgICAgICAgLy8gVW5kZWZpbmVkIHZhbHVlcyBhcmUgcmVtb3ZlZCBmcm9tIHRoZSBwcm9wcyBiZWNhdXNlIHRoZXkgc2hvdWxkbid0IG92ZXJyaWRlIGRlZmF1bHQgdmFsdWVzXG4gICAgICAgIGNvbnN0IHByb3BzV2l0aG91dFVuZGVmaW5lZCA9IE9iamVjdC5hc3NpZ24oe30sIHByb3BzKVxuXG4gICAgICAgIGZvciAoY29uc3Qga2V5IGluIHByb3BzV2l0aG91dFVuZGVmaW5lZCkge1xuICAgICAgICAgIGNvbnN0IHZhbHVlID0gcHJvcHNXaXRob3V0VW5kZWZpbmVkW2tleV1cblxuICAgICAgICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBkZWxldGUgcHJvcHNXaXRob3V0VW5kZWZpbmVkW2tleV1cbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBhY3R1YWxQcm9wcyA9IE9iamVjdC5hc3NpZ24oe30sIFNoYXBlQ2xhc3MuZGVmYXVsdFByb3BzLCBwcm9wc1dpdGhvdXRVbmRlZmluZWQpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBhY3R1YWxQcm9wcyA9IHByb3BzXG4gICAgICB9XG5cbiAgICAgIGlmIChTaGFwZUNsYXNzLnByb3BUeXBlcykge1xuICAgICAgICBjb25zdCB2YWxpZGF0ZVByb3BzID0ge31cblxuICAgICAgICBmb3IgKGNvbnN0IGtleSBpbiBhY3R1YWxQcm9wcykge1xuICAgICAgICAgIC8vIEFjY2Vzc2luZyAna2V5JyB3aWxsIHJlc3VsdCBpbiBhIHdhcm5pbmcgaW4gdGhlIGNvbnNvbGVcbiAgICAgICAgICBpZiAoa2V5ID09IFwia2V5XCIpIGNvbnRpbnVlXG5cbiAgICAgICAgICB2YWxpZGF0ZVByb3BzW2tleV0gPSBhY3R1YWxQcm9wc1trZXldXG4gICAgICAgIH1cblxuICAgICAgICBQcm9wVHlwZXMuY2hlY2tQcm9wVHlwZXMoU2hhcGVDbGFzcy5wcm9wVHlwZXMsIHZhbGlkYXRlUHJvcHMsIFwicHJvcFwiLCBTaGFwZUNsYXNzLm5hbWUpXG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHNoYXBlID0gdXNlTWVtbygoKSA9PiBuZXcgU2hhcGVDbGFzcyhhY3R1YWxQcm9wcyksIFtdKVxuICAgICAgY29uc3QgcHJldlByb3BzID0gc2hhcGUucHJvcHNcblxuICAgICAgc2hhcGUucHJvcHMgPSBhY3R1YWxQcm9wc1xuXG4gICAgICBpZiAoc2hhcGUuc2V0dXApIHtcbiAgICAgICAgc2hhcGUuc2V0dXAoKVxuICAgICAgfVxuXG4gICAgICBpZiAoc2hhcGUuY29tcG9uZW50RGlkVXBkYXRlICYmIHNoYXBlLl9fZmlyc3RSZW5kZXJDb21wbGV0ZWQgJiYgbWVtb0NvbXBhcmVQcm9wcyhzaGFwZS5wcm9wcywgcHJvcHMpKSB7XG4gICAgICAgIHNoYXBlLmNvbXBvbmVudERpZFVwZGF0ZShwcmV2UHJvcHMsIHNoYXBlLnN0YXRlKVxuICAgICAgfVxuXG4gICAgICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgICAgICBzaGFwZS5fX21vdW50aW5nID0gZmFsc2VcbiAgICAgICAgc2hhcGUuX19tb3VudGVkID0gdHJ1ZVxuXG4gICAgICAgIGlmIChzaGFwZS5jb21wb25lbnREaWRNb3VudCkge1xuICAgICAgICAgIHNoYXBlLmNvbXBvbmVudERpZE1vdW50KClcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiAoKSA9PiB7XG4gICAgICAgICAgc2hhcGUuX19tb3VudGVkID0gZmFsc2VcblxuICAgICAgICAgIGlmIChzaGFwZS5jb21wb25lbnRXaWxsVW5tb3VudCkge1xuICAgICAgICAgICAgc2hhcGUuY29tcG9uZW50V2lsbFVubW91bnQoKVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSwgW10pXG5cbiAgICAgIHNoYXBlLl9fZmlyc3RSZW5kZXJDb21wbGV0ZWQgPSB0cnVlXG5cbiAgICAgIC8vIEZpbmFsbHkgcmVuZGVyIHRoZSBjb21wb25lbnQgYW5kIHJldHVybiBpdFxuICAgICAgcmV0dXJuIHNoYXBlLnJlbmRlcigpXG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHNoYXJlZC5zY2hlZHVsZUFmdGVyUGFpbnQoKCkgPT4ge1xuICAgICAgICBzaGFyZWQucmVuZGVyaW5nID0gTWF0aC5tYXgoMCwgc2hhcmVkLnJlbmRlcmluZyAtIDEpXG4gICAgICB9KVxuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uYWxDb21wb25lbnQuZGlzcGxheU5hbWUgPSBTaGFwZUNsYXNzLm5hbWVcblxuICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZnVuY3Rpb25hbENvbXBvbmVudCwgXCJuYW1lXCIsIHt2YWx1ZTogU2hhcGVDbGFzcy5uYW1lfSlcblxuICByZXR1cm4gZnVuY3Rpb25hbENvbXBvbmVudFxufVxuXG5leHBvcnQge3NoYXBlQ29tcG9uZW50LCBTaGFwZUNvbXBvbmVudH1cbiJdfQ==