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
JavaScript
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==