strict-diff 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,98 @@
1
+ import { BuiltinType } from "builtin-type";
2
+
3
+ //#region src/index.d.ts
4
+ /**
5
+ * A path segment representing an object's own property.
6
+ *
7
+ * The path segment points to the property's {@link PropertyDescriptor}. Another
8
+ * path segment must be used to target the descriptor's `[[Value]]` slot.
9
+ *
10
+ * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Enumerability_and_ownership_of_properties
11
+ */
12
+ type PropertyPathSegment = {
13
+ kind: `property`; /** The property's index in the array returned by {@link Reflect.ownKeys}. */
14
+ index: number;
15
+ /**
16
+ * The property's key.
17
+ *
18
+ * Valid numeric indices are provided as numbers.
19
+ */
20
+ key: number | string | symbol;
21
+ };
22
+ /**
23
+ * A path segment representing an object's internal slot.
24
+ *
25
+ * @see https://tc39.es/ecma262/multipage/ecmascript-data-types-and-values.html#sec-object-internal-methods-and-internal-slots
26
+ */
27
+ type InternalSlotPathSegment = {
28
+ kind: `internal-slot`;
29
+ /**
30
+ * The name of the slot.
31
+ *
32
+ * For ECMAScript defined types, this will be the name of the internal slot
33
+ * excluding the `[[...]]` delimiters.
34
+ *
35
+ * For WHATWG defined types, this will be the name of the IDL attribute.
36
+ *
37
+ * @see https://tc39.es/ecma262/multipage/ecmascript-data-types-and-values.html#sec-object-internal-methods-and-internal-slots
38
+ * @see https://webidl.spec.whatwg.org/#idl-attributes
39
+ */
40
+ slot: string;
41
+ };
42
+ type PathSegment = PropertyPathSegment | InternalSlotPathSegment;
43
+ /**
44
+ * The path from a root value to some subvalue within it.
45
+ *
46
+ * An empty path points to the root value.
47
+ */
48
+ type Path = PathSegment[];
49
+ /** A diff between the builtin types of left and right values. */
50
+ type TypeDiff = {
51
+ kind: `type`;
52
+ /**
53
+ * The path from the left and right root values to where they have a type
54
+ * diff.
55
+ */
56
+ path: Path; /** The left value's type at {@link TypeDiff.path}. */
57
+ left: BuiltinType; /** The left value's type at {@link TypeDiff.path}. */
58
+ right: BuiltinType;
59
+ };
60
+ /** A diff between the keys of left and right objects. */
61
+ type KeyDiff = {
62
+ kind: `key`;
63
+ /**
64
+ * The path from the left and right root values to the left and right
65
+ * subobjects where they have a key diff at {@link KeyDiff.index}.
66
+ */
67
+ path: Path;
68
+ /**
69
+ * The index in the array returned by {@link Reflect.ownKeys} where the diff
70
+ * is.
71
+ */
72
+ index: number; /** The left key at {@link KeyDiff.path}. */
73
+ left: PropertyKey | undefined; /** The right key at {@link KeyDiff.path}. */
74
+ right: PropertyKey | undefined;
75
+ };
76
+ /** A diff between left and right values of the same type. */
77
+ type ValueDiff = {
78
+ kind: `value`; /** The path from the two root values to where they have a value diff. */
79
+ path: Path; /** The left value at {@link ValueDiff.path}. */
80
+ left: unknown; /** The right value at {@link ValueDiff.path}. */
81
+ right: unknown;
82
+ };
83
+ type ReferenceDiff = {
84
+ kind: `reference`; /** The path from the two root values to where they have a reference diff. */
85
+ path: Path;
86
+ /**
87
+ * The path from the left root value to where the left value was first seen.
88
+ */
89
+ leftFirstSeenPath: Path | undefined;
90
+ /**
91
+ * The path from the right root value to where the right value was first seen.
92
+ */
93
+ rightFirstSeenPath: Path | undefined;
94
+ };
95
+ type Diff = TypeDiff | KeyDiff | ValueDiff | ReferenceDiff;
96
+ declare const strictDiff: (value1: unknown, value2: unknown) => Iterable<Diff>;
97
+ //#endregion
98
+ export { Diff, InternalSlotPathSegment, KeyDiff, Path, PathSegment, PropertyPathSegment, ReferenceDiff, TypeDiff, ValueDiff, strictDiff as default };
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ import e from"builtin-type";const a=(e,a)=>({[Symbol.iterator]:()=>t(e,a,[],r())}),r=()=>({t:new Map,o:new Map});function*t(a,r,c,l){if(Object.is(a,r))return;const p=e(a),d=e(r);if(p!==d)return void(yield{kind:"type",path:[...c],left:p,right:d});if(!o(a)||!o(r))return void(yield{kind:"value",path:[...c],left:a,right:r});const T=l.t.get(a),y=l.o.get(r);T||y?n(T,y)||(yield{kind:"reference",path:[...c],leftFirstSeenPath:T,rightFirstSeenPath:y}):(l.t.set(a,c),l.o.set(r,c),yield*function*(e,a,r,o,n){const c=s(e,a),l=s(e,r),i=new Set([...Object.keys(c),...Object.keys(l)]);for(const e of i)yield*t(c[e],l[e],[...o,{kind:"internal-slot",slot:e}],n)}(p,a,r,c,l),yield*function*(e,a,r,o){const n=Reflect.ownKeys(e),c=Reflect.ownKeys(a),s=Math.max(n.length,c.length);for(let l=0;l<s;l++){const s=i(n[l]),p=i(c[l]);if(s!==p){yield{kind:"key",path:[...r],index:l,left:s,right:p};continue}const d=s,T=Object.getOwnPropertyDescriptor(e,d),y=Object.getOwnPropertyDescriptor(a,d);for(const e of m)yield*t(T[e],y[e],[...r,{kind:"property",index:l,key:d},{kind:"internal-slot",slot:e[0].toUpperCase()+e.slice(1)}],o)}}(a,r,c,l))}const o=e=>{const a=typeof e;return"object"===a&&!!e||"function"===a},n=(e,a)=>e===a||!(!e||!a)&&(e.length===a.length&&e.every((e,r)=>c(e,a[r]))),c=(e,a)=>{if(e.kind!==a.kind)return!1;switch(e.kind){case"property":{const r=a;return e.index===r.index&&e.key===r.key}case"internal-slot":return e.slot===a.slot}};const s=(e,a)=>{const r={Prototype:Object.getPrototypeOf(a),Extensible:Object.isExtensible(a)};switch(e){case"Boolean":case"Number":case"BigInt":case"String":case"Symbol":{const t=globalThis[e].prototype.valueOf;r[`${e}Data`]=t.call(a);break}case"Map":r.MapData=[...Map.prototype.entries.call(a)];break;case"Set":r.SetData=[...Set.prototype.values.call(a)];break;case"Function":case"GeneratorFunction":case"AsyncFunction":case"AsyncGeneratorFunction":r.SourceText=Function.prototype.toString.call(a);break;case"Date":r.DateValue=Date.prototype.getTime.call(a);break;case"RegExp":r.OriginalSource=l(RegExp,"source",a),r.OriginalFlags=l(RegExp,"flags",a);break;case"URL":r.href=l(URL,"href",a);break;case"URLSearchParams":r.list=URLSearchParams.prototype.toString.call(a);break;case"WeakRef":r.WeakRefTarget=WeakRef.prototype.deref.call(a);break;case"ArrayBuffer":if(l(ArrayBuffer,"detached",a)){r.ArrayBufferData=null;break}case"SharedArrayBuffer":{const t=globalThis[e];r.ArrayBufferByteLength=l(t,"byteLength",a),r.ArrayBufferMaxByteLength=l(t,"maxByteLength",a),r.ArrayBufferData=[...new Uint8Array(a)];break}case"Buffer":case"Int8Array":case"Uint8Array":case"Uint8ClampedArray":case"Int16Array":case"Uint16Array":case"Int32Array":case"Uint32Array":case"BigInt64Array":case"BigUint64Array":case"Float16Array":case"Float32Array":case"Float64Array":case"DataView":{const t=globalThis[e];r.ByteOffset=l(t,"byteOffset",a),r.ByteLength=l(t,"byteLength",a),r.ViewedArrayBuffer=l(t,"buffer",a);break}case"Temporal.Duration":r.Years=l(Temporal.Duration,"years",a),r.Months=l(Temporal.Duration,"months",a),r.Weeks=l(Temporal.Duration,"weeks",a),r.Days=l(Temporal.Duration,"days",a),r.Hours=l(Temporal.Duration,"hours",a),r.Minutes=l(Temporal.Duration,"minutes",a),r.Seconds=l(Temporal.Duration,"seconds",a),r.Milliseconds=l(Temporal.Duration,"milliseconds",a),r.Microseconds=l(Temporal.Duration,"microseconds",a),r.Nanoseconds=l(Temporal.Duration,"nanoseconds",a);break;case"Temporal.Instant":r.EpochNanoseconds=l(Temporal.Instant,"epochNanoseconds",a);break;case"Temporal.PlainDate":r.Calendar=l(Temporal.PlainDate,"calendarId",a),r.Year=l(Temporal.PlainDate,"year",a),r.Month=l(Temporal.PlainDate,"month",a),r.Day=l(Temporal.PlainDate,"day",a);break;case"Temporal.PlainDateTime":r.Calendar=l(Temporal.PlainDateTime,"calendarId",a),r.Year=l(Temporal.PlainDateTime,"year",a),r.Month=l(Temporal.PlainDateTime,"month",a),r.Day=l(Temporal.PlainDateTime,"day",a),r.Hour=l(Temporal.PlainDateTime,"hour",a),r.Minute=l(Temporal.PlainDateTime,"minute",a),r.Second=l(Temporal.PlainDateTime,"second",a),r.Millisecond=l(Temporal.PlainDateTime,"millisecond",a),r.Microsecond=l(Temporal.PlainDateTime,"microsecond",a),r.Nanosecond=l(Temporal.PlainDateTime,"nanosecond",a);break;case"Temporal.PlainMonthDay":r.Calendar=l(Temporal.PlainMonthDay,"calendarId",a),r.MonthCode=l(Temporal.PlainMonthDay,"monthCode",a),r.Day=l(Temporal.PlainMonthDay,"day",a);break;case"Temporal.PlainTime":r.Hour=l(Temporal.PlainTime,"hour",a),r.Minute=l(Temporal.PlainTime,"minute",a),r.Second=l(Temporal.PlainTime,"second",a),r.Millisecond=l(Temporal.PlainTime,"millisecond",a),r.Microsecond=l(Temporal.PlainTime,"microsecond",a),r.Nanosecond=l(Temporal.PlainTime,"nanosecond",a);break;case"Temporal.PlainYearMonth":r.Calendar=l(Temporal.PlainYearMonth,"calendarId",a),r.Year=l(Temporal.PlainYearMonth,"year",a),r.Month=l(Temporal.PlainYearMonth,"month",a);break;case"Temporal.ZonedDateTime":r.Calendar=l(Temporal.ZonedDateTime,"calendarId",a),r.TimeZone=l(Temporal.ZonedDateTime,"timeZoneId",a),r.EpochNanoseconds=l(Temporal.ZonedDateTime,"epochNanoseconds",a)}return r},l=(e,a,r)=>{for(let t=e.prototype;t;t=Object.getPrototypeOf(t)){const e=Object.getOwnPropertyDescriptor(t,a);if(e)return e.get.call(r)}};const i=e=>{if(void 0===e)return;if("string"!=typeof e)return e;const a=Number(e);return Number.isInteger(a)&&a>=0&&a<=2**32-2&&String(a)===e?a:e},m=["configurable","enumerable","writable","value","get","set"];export{a as default};
2
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vc3JjL2luZGV4LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBidWlsdGluVHlwZSBmcm9tICdidWlsdGluLXR5cGUnXG5pbXBvcnQgdHlwZSB7IEJ1aWx0aW5UeXBlIH0gZnJvbSAnYnVpbHRpbi10eXBlJ1xuXG4vKipcbiAqIEEgcGF0aCBzZWdtZW50IHJlcHJlc2VudGluZyBhbiBvYmplY3QncyBvd24gcHJvcGVydHkuXG4gKlxuICogVGhlIHBhdGggc2VnbWVudCBwb2ludHMgdG8gdGhlIHByb3BlcnR5J3Mge0BsaW5rIFByb3BlcnR5RGVzY3JpcHRvcn0uIEFub3RoZXJcbiAqIHBhdGggc2VnbWVudCBtdXN0IGJlIHVzZWQgdG8gdGFyZ2V0IHRoZSBkZXNjcmlwdG9yJ3MgYFtbVmFsdWVdXWAgc2xvdC5cbiAqXG4gKiBAc2VlIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvR3VpZGUvRW51bWVyYWJpbGl0eV9hbmRfb3duZXJzaGlwX29mX3Byb3BlcnRpZXNcbiAqL1xuZXhwb3J0IHR5cGUgUHJvcGVydHlQYXRoU2VnbWVudCA9IHtcbiAga2luZDogYHByb3BlcnR5YFxuXG4gIC8qKiBUaGUgcHJvcGVydHkncyBpbmRleCBpbiB0aGUgYXJyYXkgcmV0dXJuZWQgYnkge0BsaW5rIFJlZmxlY3Qub3duS2V5c30uICovXG4gIGluZGV4OiBudW1iZXJcblxuICAvKipcbiAgICogVGhlIHByb3BlcnR5J3Mga2V5LlxuICAgKlxuICAgKiBWYWxpZCBudW1lcmljIGluZGljZXMgYXJlIHByb3ZpZGVkIGFzIG51bWJlcnMuXG4gICAqL1xuICBrZXk6IG51bWJlciB8IHN0cmluZyB8IHN5bWJvbFxufVxuXG4vKipcbiAqIEEgcGF0aCBzZWdtZW50IHJlcHJlc2VudGluZyBhbiBvYmplY3QncyBpbnRlcm5hbCBzbG90LlxuICpcbiAqIEBzZWUgaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvbXVsdGlwYWdlL2VjbWFzY3JpcHQtZGF0YS10eXBlcy1hbmQtdmFsdWVzLmh0bWwjc2VjLW9iamVjdC1pbnRlcm5hbC1tZXRob2RzLWFuZC1pbnRlcm5hbC1zbG90c1xuICovXG5leHBvcnQgdHlwZSBJbnRlcm5hbFNsb3RQYXRoU2VnbWVudCA9IHtcbiAga2luZDogYGludGVybmFsLXNsb3RgXG5cbiAgLyoqXG4gICAqIFRoZSBuYW1lIG9mIHRoZSBzbG90LlxuICAgKlxuICAgKiBGb3IgRUNNQVNjcmlwdCBkZWZpbmVkIHR5cGVzLCB0aGlzIHdpbGwgYmUgdGhlIG5hbWUgb2YgdGhlIGludGVybmFsIHNsb3RcbiAgICogZXhjbHVkaW5nIHRoZSBgW1suLi5dXWAgZGVsaW1pdGVycy5cbiAgICpcbiAgICogRm9yIFdIQVRXRyBkZWZpbmVkIHR5cGVzLCB0aGlzIHdpbGwgYmUgdGhlIG5hbWUgb2YgdGhlIElETCBhdHRyaWJ1dGUuXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvbXVsdGlwYWdlL2VjbWFzY3JpcHQtZGF0YS10eXBlcy1hbmQtdmFsdWVzLmh0bWwjc2VjLW9iamVjdC1pbnRlcm5hbC1tZXRob2RzLWFuZC1pbnRlcm5hbC1zbG90c1xuICAgKiBAc2VlIGh0dHBzOi8vd2ViaWRsLnNwZWMud2hhdHdnLm9yZy8jaWRsLWF0dHJpYnV0ZXNcbiAgICovXG4gIHNsb3Q6IHN0cmluZ1xufVxuXG5leHBvcnQgdHlwZSBQYXRoU2VnbWVudCA9IFByb3BlcnR5UGF0aFNlZ21lbnQgfCBJbnRlcm5hbFNsb3RQYXRoU2VnbWVudFxuXG4vKipcbiAqIFRoZSBwYXRoIGZyb20gYSByb290IHZhbHVlIHRvIHNvbWUgc3VidmFsdWUgd2l0aGluIGl0LlxuICpcbiAqIEFuIGVtcHR5IHBhdGggcG9pbnRzIHRvIHRoZSByb290IHZhbHVlLlxuICovXG5leHBvcnQgdHlwZSBQYXRoID0gUGF0aFNlZ21lbnRbXVxuXG4vKiogQSBkaWZmIGJldHdlZW4gdGhlIGJ1aWx0aW4gdHlwZXMgb2YgbGVmdCBhbmQgcmlnaHQgdmFsdWVzLiAqL1xuZXhwb3J0IHR5cGUgVHlwZURpZmYgPSB7XG4gIGtpbmQ6IGB0eXBlYFxuXG4gIC8qKlxuICAgKiBUaGUgcGF0aCBmcm9tIHRoZSBsZWZ0IGFuZCByaWdodCByb290IHZhbHVlcyB0byB3aGVyZSB0aGV5IGhhdmUgYSB0eXBlXG4gICAqIGRpZmYuXG4gICAqL1xuICBwYXRoOiBQYXRoXG5cbiAgLyoqIFRoZSBsZWZ0IHZhbHVlJ3MgdHlwZSBhdCB7QGxpbmsgVHlwZURpZmYucGF0aH0uICovXG4gIGxlZnQ6IEJ1aWx0aW5UeXBlXG5cbiAgLyoqIFRoZSBsZWZ0IHZhbHVlJ3MgdHlwZSBhdCB7QGxpbmsgVHlwZURpZmYucGF0aH0uICovXG4gIHJpZ2h0OiBCdWlsdGluVHlwZVxufVxuXG4vKiogQSBkaWZmIGJldHdlZW4gdGhlIGtleXMgb2YgbGVmdCBhbmQgcmlnaHQgb2JqZWN0cy4gKi9cbmV4cG9ydCB0eXBlIEtleURpZmYgPSB7XG4gIGtpbmQ6IGBrZXlgXG5cbiAgLyoqXG4gICAqIFRoZSBwYXRoIGZyb20gdGhlIGxlZnQgYW5kIHJpZ2h0IHJvb3QgdmFsdWVzIHRvIHRoZSBsZWZ0IGFuZCByaWdodFxuICAgKiBzdWJvYmplY3RzIHdoZXJlIHRoZXkgaGF2ZSBhIGtleSBkaWZmIGF0IHtAbGluayBLZXlEaWZmLmluZGV4fS5cbiAgICovXG4gIHBhdGg6IFBhdGhcblxuICAvKipcbiAgICogVGhlIGluZGV4IGluIHRoZSBhcnJheSByZXR1cm5lZCBieSB7QGxpbmsgUmVmbGVjdC5vd25LZXlzfSB3aGVyZSB0aGUgZGlmZlxuICAgKiBpcy5cbiAgICovXG4gIGluZGV4OiBudW1iZXJcblxuICAvKiogVGhlIGxlZnQga2V5IGF0IHtAbGluayBLZXlEaWZmLnBhdGh9LiAqL1xuICBsZWZ0OiBQcm9wZXJ0eUtleSB8IHVuZGVmaW5lZFxuXG4gIC8qKiBUaGUgcmlnaHQga2V5IGF0IHtAbGluayBLZXlEaWZmLnBhdGh9LiAqL1xuICByaWdodDogUHJvcGVydHlLZXkgfCB1bmRlZmluZWRcbn1cblxuLyoqIEEgZGlmZiBiZXR3ZWVuIGxlZnQgYW5kIHJpZ2h0IHZhbHVlcyBvZiB0aGUgc2FtZSB0eXBlLiAqL1xuZXhwb3J0IHR5cGUgVmFsdWVEaWZmID0ge1xuICBraW5kOiBgdmFsdWVgXG5cbiAgLyoqIFRoZSBwYXRoIGZyb20gdGhlIHR3byByb290IHZhbHVlcyB0byB3aGVyZSB0aGV5IGhhdmUgYSB2YWx1ZSBkaWZmLiAqL1xuICBwYXRoOiBQYXRoXG5cbiAgLyoqIFRoZSBsZWZ0IHZhbHVlIGF0IHtAbGluayBWYWx1ZURpZmYucGF0aH0uICovXG4gIGxlZnQ6IHVua25vd25cblxuICAvKiogVGhlIHJpZ2h0IHZhbHVlIGF0IHtAbGluayBWYWx1ZURpZmYucGF0aH0uICovXG4gIHJpZ2h0OiB1bmtub3duXG59XG5cbmV4cG9ydCB0eXBlIFJlZmVyZW5jZURpZmYgPSB7XG4gIGtpbmQ6IGByZWZlcmVuY2VgXG5cbiAgLyoqIFRoZSBwYXRoIGZyb20gdGhlIHR3byByb290IHZhbHVlcyB0byB3aGVyZSB0aGV5IGhhdmUgYSByZWZlcmVuY2UgZGlmZi4gKi9cbiAgcGF0aDogUGF0aFxuXG4gIC8qKlxuICAgKiBUaGUgcGF0aCBmcm9tIHRoZSBsZWZ0IHJvb3QgdmFsdWUgdG8gd2hlcmUgdGhlIGxlZnQgdmFsdWUgd2FzIGZpcnN0IHNlZW4uXG4gICAqL1xuICBsZWZ0Rmlyc3RTZWVuUGF0aDogUGF0aCB8IHVuZGVmaW5lZFxuXG4gIC8qKlxuICAgKiBUaGUgcGF0aCBmcm9tIHRoZSByaWdodCByb290IHZhbHVlIHRvIHdoZXJlIHRoZSByaWdodCB2YWx1ZSB3YXMgZmlyc3Qgc2Vlbi5cbiAgICovXG4gIHJpZ2h0Rmlyc3RTZWVuUGF0aDogUGF0aCB8IHVuZGVmaW5lZFxufVxuXG5leHBvcnQgdHlwZSBEaWZmID0gVHlwZURpZmYgfCBLZXlEaWZmIHwgVmFsdWVEaWZmIHwgUmVmZXJlbmNlRGlmZlxuXG5jb25zdCBzdHJpY3REaWZmID0gKHZhbHVlMTogdW5rbm93biwgdmFsdWUyOiB1bmtub3duKTogSXRlcmFibGU8RGlmZj4gPT4gKHtcbiAgW1N5bWJvbC5pdGVyYXRvcl06ICgpID0+IGVudW1lcmF0ZURpZmZzKHZhbHVlMSwgdmFsdWUyLCBbXSwgbWFrZVN0YXRlKCkpLFxufSlcblxudHlwZSBTdGF0ZSA9IHtcbiAgX2xlZnRGaXJzdFNlZW5QYXRoczogTWFwPG9iamVjdCwgUGF0aD5cbiAgX3JpZ2h0Rmlyc3RTZWVuUGF0aHM6IE1hcDxvYmplY3QsIFBhdGg+XG59XG5cbmNvbnN0IG1ha2VTdGF0ZSA9ICgpOiBTdGF0ZSA9PiAoe1xuICBfbGVmdEZpcnN0U2VlblBhdGhzOiBuZXcgTWFwKCksXG4gIF9yaWdodEZpcnN0U2VlblBhdGhzOiBuZXcgTWFwKCksXG59KVxuXG5mdW5jdGlvbiogZW51bWVyYXRlRGlmZnMoXG4gIGxlZnQ6IHVua25vd24sXG4gIHJpZ2h0OiB1bmtub3duLFxuICBwYXRoOiBQYXRoLFxuICBzdGF0ZTogU3RhdGUsXG4pOiBJdGVyYWJsZUl0ZXJhdG9yPERpZmY+IHtcbiAgaWYgKE9iamVjdC5pcyhsZWZ0LCByaWdodCkpIHtcbiAgICByZXR1cm5cbiAgfVxuXG4gIGNvbnN0IGxlZnRUeXBlID0gYnVpbHRpblR5cGUobGVmdClcbiAgY29uc3QgcmlnaHRUeXBlID0gYnVpbHRpblR5cGUocmlnaHQpXG4gIGlmIChsZWZ0VHlwZSAhPT0gcmlnaHRUeXBlKSB7XG4gICAgeWllbGQgeyBraW5kOiBgdHlwZWAsIHBhdGg6IFsuLi5wYXRoXSwgbGVmdDogbGVmdFR5cGUsIHJpZ2h0OiByaWdodFR5cGUgfVxuICAgIHJldHVyblxuICB9XG5cbiAgaWYgKCFpc09iamVjdChsZWZ0KSB8fCAhaXNPYmplY3QocmlnaHQpKSB7XG4gICAgeWllbGQgeyBraW5kOiBgdmFsdWVgLCBwYXRoOiBbLi4ucGF0aF0sIGxlZnQsIHJpZ2h0IH1cbiAgICByZXR1cm5cbiAgfVxuXG4gIGNvbnN0IGxlZnRGaXJzdFNlZW5QYXRoID0gc3RhdGUuX2xlZnRGaXJzdFNlZW5QYXRocy5nZXQobGVmdClcbiAgY29uc3QgcmlnaHRGaXJzdFNlZW5QYXRoID0gc3RhdGUuX3JpZ2h0Rmlyc3RTZWVuUGF0aHMuZ2V0KHJpZ2h0KVxuICBpZiAobGVmdEZpcnN0U2VlblBhdGggfHwgcmlnaHRGaXJzdFNlZW5QYXRoKSB7XG4gICAgaWYgKCFwYXRoc0VxdWFsKGxlZnRGaXJzdFNlZW5QYXRoLCByaWdodEZpcnN0U2VlblBhdGgpKSB7XG4gICAgICB5aWVsZCB7XG4gICAgICAgIGtpbmQ6IGByZWZlcmVuY2VgLFxuICAgICAgICBwYXRoOiBbLi4ucGF0aF0sXG4gICAgICAgIGxlZnRGaXJzdFNlZW5QYXRoLFxuICAgICAgICByaWdodEZpcnN0U2VlblBhdGgsXG4gICAgICB9XG4gICAgfVxuICAgIHJldHVyblxuICB9XG4gIHN0YXRlLl9sZWZ0Rmlyc3RTZWVuUGF0aHMuc2V0KGxlZnQsIHBhdGgpXG4gIHN0YXRlLl9yaWdodEZpcnN0U2VlblBhdGhzLnNldChyaWdodCwgcGF0aClcblxuICB5aWVsZCogZW51bWVyYXRlSW50ZXJuYWxTbG90RGlmZnMobGVmdFR5cGUsIGxlZnQsIHJpZ2h0LCBwYXRoLCBzdGF0ZSlcbiAgeWllbGQqIGVudW1lcmF0ZU93blByb3BlcnR5RGlmZnMobGVmdCwgcmlnaHQsIHBhdGgsIHN0YXRlKVxufVxuXG5jb25zdCBpc09iamVjdCA9ICh2YWx1ZTogdW5rbm93bik6IHZhbHVlIGlzIG9iamVjdCA9PiB7XG4gIGNvbnN0IHR5cGUgPSB0eXBlb2YgdmFsdWVcbiAgcmV0dXJuICh0eXBlID09PSBgb2JqZWN0YCAmJiAhIXZhbHVlKSB8fCB0eXBlID09PSBgZnVuY3Rpb25gXG59XG5cbmNvbnN0IHBhdGhzRXF1YWwgPSAoXG4gIHBhdGgxOiBQYXRoIHwgdW5kZWZpbmVkLFxuICBwYXRoMjogUGF0aCB8IHVuZGVmaW5lZCxcbik6IGJvb2xlYW4gPT4ge1xuICBpZiAocGF0aDEgPT09IHBhdGgyKSB7XG4gICAgcmV0dXJuIHRydWVcbiAgfVxuICBpZiAoIXBhdGgxIHx8ICFwYXRoMikge1xuICAgIHJldHVybiBmYWxzZVxuICB9XG4gIGlmIChwYXRoMS5sZW5ndGggIT09IHBhdGgyLmxlbmd0aCkge1xuICAgIHJldHVybiBmYWxzZVxuICB9XG4gIHJldHVybiBwYXRoMS5ldmVyeSgoc2VnbWVudCwgaW5kZXgpID0+XG4gICAgcGF0aFNlZ21lbnRzRXF1YWwoc2VnbWVudCwgcGF0aDJbaW5kZXhdISksXG4gIClcbn1cblxuY29uc3QgcGF0aFNlZ21lbnRzRXF1YWwgPSAoXG4gIHNlZ21lbnQxOiBQYXRoU2VnbWVudCxcbiAgc2VnbWVudDI6IFBhdGhTZWdtZW50LFxuKTogYm9vbGVhbiA9PiB7XG4gIGlmIChzZWdtZW50MS5raW5kICE9PSBzZWdtZW50Mi5raW5kKSB7XG4gICAgcmV0dXJuIGZhbHNlXG4gIH1cblxuICBzd2l0Y2ggKHNlZ21lbnQxLmtpbmQpIHtcbiAgICBjYXNlIGBwcm9wZXJ0eWA6IHtcbiAgICAgIGNvbnN0IHByb3BlcnR5U2VnbWVudDIgPSBzZWdtZW50MiBhcyBQcm9wZXJ0eVBhdGhTZWdtZW50XG4gICAgICByZXR1cm4gKFxuICAgICAgICBzZWdtZW50MS5pbmRleCA9PT0gcHJvcGVydHlTZWdtZW50Mi5pbmRleCAmJlxuICAgICAgICBzZWdtZW50MS5rZXkgPT09IHByb3BlcnR5U2VnbWVudDIua2V5XG4gICAgICApXG4gICAgfVxuICAgIGNhc2UgYGludGVybmFsLXNsb3RgOlxuICAgICAgcmV0dXJuIHNlZ21lbnQxLnNsb3QgPT09IChzZWdtZW50MiBhcyBJbnRlcm5hbFNsb3RQYXRoU2VnbWVudCkuc2xvdFxuICB9XG59XG5cbmZ1bmN0aW9uKiBlbnVtZXJhdGVJbnRlcm5hbFNsb3REaWZmcyhcbiAgdHlwZTogQnVpbHRpblR5cGUsXG4gIGxlZnQ6IG9iamVjdCxcbiAgcmlnaHQ6IG9iamVjdCxcbiAgcGF0aDogUGF0aCxcbiAgc3RhdGU6IFN0YXRlLFxuKTogR2VuZXJhdG9yPERpZmY+IHtcbiAgY29uc3QgbGVmdFNsb3RzID0gZ2V0SW50ZXJuYWxTbG90cyh0eXBlLCBsZWZ0KVxuICBjb25zdCByaWdodFNsb3RzID0gZ2V0SW50ZXJuYWxTbG90cyh0eXBlLCByaWdodClcblxuICBjb25zdCBzbG90cyA9IG5ldyBTZXQoWy4uLk9iamVjdC5rZXlzKGxlZnRTbG90cyksIC4uLk9iamVjdC5rZXlzKHJpZ2h0U2xvdHMpXSlcbiAgZm9yIChjb25zdCBzbG90IG9mIHNsb3RzKSB7XG4gICAgeWllbGQqIGVudW1lcmF0ZURpZmZzKFxuICAgICAgbGVmdFNsb3RzW3Nsb3RdLFxuICAgICAgcmlnaHRTbG90c1tzbG90XSxcbiAgICAgIFsuLi5wYXRoLCB7IGtpbmQ6IGBpbnRlcm5hbC1zbG90YCwgc2xvdCB9XSxcbiAgICAgIHN0YXRlLFxuICAgIClcbiAgfVxufVxuXG5jb25zdCBnZXRJbnRlcm5hbFNsb3RzID0gKFxuICB0eXBlOiBCdWlsdGluVHlwZSxcbiAgdmFsdWU6IG9iamVjdCxcbik6IFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0+IHtcbiAgY29uc3Qgc2xvdHM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0ge1xuICAgIFByb3RvdHlwZTogT2JqZWN0LmdldFByb3RvdHlwZU9mKHZhbHVlKSxcbiAgICBFeHRlbnNpYmxlOiBPYmplY3QuaXNFeHRlbnNpYmxlKHZhbHVlKSxcbiAgfVxuXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvc3dpdGNoLWV4aGF1c3RpdmVuZXNzLWNoZWNrXG4gIHN3aXRjaCAodHlwZSkge1xuICAgIGNhc2UgYEJvb2xlYW5gOlxuICAgIGNhc2UgYE51bWJlcmA6XG4gICAgY2FzZSBgQmlnSW50YDpcbiAgICBjYXNlIGBTdHJpbmdgOlxuICAgIGNhc2UgYFN5bWJvbGA6IHtcbiAgICAgIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtdGhpc2Jvb2xlYW52YWx1ZVxuICAgICAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy10aGlzbnVtYmVydmFsdWVcbiAgICAgIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtdGhpc2JpZ2ludHZhbHVlXG4gICAgICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLXRoaXNzdHJpbmd2YWx1ZVxuICAgICAgLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy10aGlzc3ltYm9sdmFsdWVcbiAgICAgIGNvbnN0IHZhbHVlT2Y6ICh0aGlzOiBvYmplY3QpID0+IHVua25vd24gPVxuICAgICAgICBnbG9iYWxUaGlzW3R5cGVdLnByb3RvdHlwZS52YWx1ZU9mXG4gICAgICBzbG90c1tgJHt0eXBlfURhdGFgXSA9IHZhbHVlT2YuY2FsbCh2YWx1ZSlcbiAgICAgIGJyZWFrXG4gICAgfVxuICAgIGNhc2UgYE1hcGA6XG4gICAgICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLWNyZWF0ZW1hcGl0ZXJhdG9yXG4gICAgICBzbG90cy5NYXBEYXRhID0gWy4uLk1hcC5wcm90b3R5cGUuZW50cmllcy5jYWxsKHZhbHVlKV1cbiAgICAgIGJyZWFrXG4gICAgY2FzZSBgU2V0YDpcbiAgICAgIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtY3JlYXRlc2V0aXRlcmF0b3JcbiAgICAgIHNsb3RzLlNldERhdGEgPSBbLi4uU2V0LnByb3RvdHlwZS52YWx1ZXMuY2FsbCh2YWx1ZSldXG4gICAgICBicmVha1xuICAgIGNhc2UgYEZ1bmN0aW9uYDpcbiAgICBjYXNlIGBHZW5lcmF0b3JGdW5jdGlvbmA6XG4gICAgY2FzZSBgQXN5bmNGdW5jdGlvbmA6XG4gICAgY2FzZSBgQXN5bmNHZW5lcmF0b3JGdW5jdGlvbmA6XG4gICAgICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLWZ1bmN0aW9uLnByb3RvdHlwZS50b3N0cmluZ1xuICAgICAgc2xvdHMuU291cmNlVGV4dCA9IEZ1bmN0aW9uLnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHZhbHVlKVxuICAgICAgYnJlYWtcbiAgICBjYXNlIGBEYXRlYDpcbiAgICAgIC8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtZGF0ZS5wcm90b3R5cGUuZ2V0dGltZVxuICAgICAgc2xvdHMuRGF0ZVZhbHVlID0gRGF0ZS5wcm90b3R5cGUuZ2V0VGltZS5jYWxsKHZhbHVlIGFzIERhdGUpXG4gICAgICBicmVha1xuICAgIGNhc2UgYFJlZ0V4cGA6XG4gICAgICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLWdldC1yZWdleHAucHJvdG90eXBlLnNvdXJjZVxuICAgICAgc2xvdHMuT3JpZ2luYWxTb3VyY2UgPSBhY2Nlc3NHZXR0ZXIoUmVnRXhwLCBgc291cmNlYCwgdmFsdWUpXG4gICAgICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLWdldC1yZWdleHAucHJvdG90eXBlLmZsYWdzXG4gICAgICBzbG90cy5PcmlnaW5hbEZsYWdzID0gYWNjZXNzR2V0dGVyKFJlZ0V4cCwgYGZsYWdzYCwgdmFsdWUpXG4gICAgICBicmVha1xuICAgIGNhc2UgYFVSTGA6XG4gICAgICAvLyBodHRwczovL3VybC5zcGVjLndoYXR3Zy5vcmcvI3VybC1jbGFzc1xuICAgICAgc2xvdHMuaHJlZiA9IGFjY2Vzc0dldHRlcihVUkwsIGBocmVmYCwgdmFsdWUpXG4gICAgICBicmVha1xuICAgIGNhc2UgYFVSTFNlYXJjaFBhcmFtc2A6XG4gICAgICAvLyBodHRwczovL3VybC5zcGVjLndoYXR3Zy5vcmcvI3VybHNlYXJjaHBhcmFtc1xuICAgICAgc2xvdHMubGlzdCA9IFVSTFNlYXJjaFBhcmFtcy5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh2YWx1ZSlcbiAgICAgIGJyZWFrXG4gICAgY2FzZSBgV2Vha1JlZmA6XG4gICAgICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLXdlYWstcmVmLnByb3RvdHlwZS5kZXJlZlxuICAgICAgc2xvdHMuV2Vha1JlZlRhcmdldCA9IFdlYWtSZWYucHJvdG90eXBlLmRlcmVmLmNhbGwodmFsdWUpXG4gICAgICBicmVha1xuICAgIGNhc2UgYEFycmF5QnVmZmVyYDpcbiAgICAgIGlmIChhY2Nlc3NHZXR0ZXIoQXJyYXlCdWZmZXIsIGBkZXRhY2hlZGAsIHZhbHVlKSkge1xuICAgICAgICBzbG90cy5BcnJheUJ1ZmZlckRhdGEgPSBudWxsXG4gICAgICAgIGJyZWFrXG4gICAgICB9XG4gICAgLy8gRmFsbHMgdGhyb3VnaCBvbiBwdXJwb3NlLlxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1mYWxsdGhyb3VnaFxuICAgIGNhc2UgYFNoYXJlZEFycmF5QnVmZmVyYDoge1xuICAgICAgY29uc3QgQ2xhc3MgPSBnbG9iYWxUaGlzW3R5cGVdXG4gICAgICBzbG90cy5BcnJheUJ1ZmZlckJ5dGVMZW5ndGggPSBhY2Nlc3NHZXR0ZXIoQ2xhc3MsIGBieXRlTGVuZ3RoYCwgdmFsdWUpXG4gICAgICBzbG90cy5BcnJheUJ1ZmZlck1heEJ5dGVMZW5ndGggPSBhY2Nlc3NHZXR0ZXIoXG4gICAgICAgIENsYXNzLFxuICAgICAgICBgbWF4Qnl0ZUxlbmd0aGAsXG4gICAgICAgIHZhbHVlLFxuICAgICAgKVxuICAgICAgc2xvdHMuQXJyYXlCdWZmZXJEYXRhID0gW1xuICAgICAgICAuLi5uZXcgVWludDhBcnJheSh2YWx1ZSBhcyBBcnJheUJ1ZmZlciB8IFNoYXJlZEFycmF5QnVmZmVyKSxcbiAgICAgIF1cbiAgICAgIGJyZWFrXG4gICAgfVxuICAgIGNhc2UgYEJ1ZmZlcmA6XG4gICAgY2FzZSBgSW50OEFycmF5YDpcbiAgICBjYXNlIGBVaW50OEFycmF5YDpcbiAgICBjYXNlIGBVaW50OENsYW1wZWRBcnJheWA6XG4gICAgY2FzZSBgSW50MTZBcnJheWA6XG4gICAgY2FzZSBgVWludDE2QXJyYXlgOlxuICAgIGNhc2UgYEludDMyQXJyYXlgOlxuICAgIGNhc2UgYFVpbnQzMkFycmF5YDpcbiAgICBjYXNlIGBCaWdJbnQ2NEFycmF5YDpcbiAgICBjYXNlIGBCaWdVaW50NjRBcnJheWA6XG4gICAgY2FzZSBgRmxvYXQxNkFycmF5YDpcbiAgICBjYXNlIGBGbG9hdDMyQXJyYXlgOlxuICAgIGNhc2UgYEZsb2F0NjRBcnJheWA6XG4gICAgY2FzZSBgRGF0YVZpZXdgOiB7XG4gICAgICBjb25zdCBDbGFzcyA9IGdsb2JhbFRoaXNbdHlwZV1cbiAgICAgIHNsb3RzLkJ5dGVPZmZzZXQgPSBhY2Nlc3NHZXR0ZXIoQ2xhc3MsIGBieXRlT2Zmc2V0YCwgdmFsdWUpXG4gICAgICBzbG90cy5CeXRlTGVuZ3RoID0gYWNjZXNzR2V0dGVyKENsYXNzLCBgYnl0ZUxlbmd0aGAsIHZhbHVlKVxuICAgICAgc2xvdHMuVmlld2VkQXJyYXlCdWZmZXIgPSBhY2Nlc3NHZXR0ZXIoQ2xhc3MsIGBidWZmZXJgLCB2YWx1ZSlcbiAgICAgIGJyZWFrXG4gICAgfVxuICAgIGNhc2UgYFRlbXBvcmFsLkR1cmF0aW9uYDpcbiAgICAgIHNsb3RzLlllYXJzID0gYWNjZXNzR2V0dGVyKFRlbXBvcmFsLkR1cmF0aW9uLCBgeWVhcnNgLCB2YWx1ZSlcbiAgICAgIHNsb3RzLk1vbnRocyA9IGFjY2Vzc0dldHRlcihUZW1wb3JhbC5EdXJhdGlvbiwgYG1vbnRoc2AsIHZhbHVlKVxuICAgICAgc2xvdHMuV2Vla3MgPSBhY2Nlc3NHZXR0ZXIoVGVtcG9yYWwuRHVyYXRpb24sIGB3ZWVrc2AsIHZhbHVlKVxuICAgICAgc2xvdHMuRGF5cyA9IGFjY2Vzc0dldHRlcihUZW1wb3JhbC5EdXJhdGlvbiwgYGRheXNgLCB2YWx1ZSlcbiAgICAgIHNsb3RzLkhvdXJzID0gYWNjZXNzR2V0dGVyKFRlbXBvcmFsLkR1cmF0aW9uLCBgaG91cnNgLCB2YWx1ZSlcbiAgICAgIHNsb3RzLk1pbnV0ZXMgPSBhY2Nlc3NHZXR0ZXIoVGVtcG9yYWwuRHVyYXRpb24sIGBtaW51dGVzYCwgdmFsdWUpXG4gICAgICBzbG90cy5TZWNvbmRzID0gYWNjZXNzR2V0dGVyKFRlbXBvcmFsLkR1cmF0aW9uLCBgc2Vjb25kc2AsIHZhbHVlKVxuICAgICAgc2xvdHMuTWlsbGlzZWNvbmRzID0gYWNjZXNzR2V0dGVyKFxuICAgICAgICBUZW1wb3JhbC5EdXJhdGlvbixcbiAgICAgICAgYG1pbGxpc2Vjb25kc2AsXG4gICAgICAgIHZhbHVlLFxuICAgICAgKVxuICAgICAgc2xvdHMuTWljcm9zZWNvbmRzID0gYWNjZXNzR2V0dGVyKFxuICAgICAgICBUZW1wb3JhbC5EdXJhdGlvbixcbiAgICAgICAgYG1pY3Jvc2Vjb25kc2AsXG4gICAgICAgIHZhbHVlLFxuICAgICAgKVxuICAgICAgc2xvdHMuTmFub3NlY29uZHMgPSBhY2Nlc3NHZXR0ZXIoVGVtcG9yYWwuRHVyYXRpb24sIGBuYW5vc2Vjb25kc2AsIHZhbHVlKVxuICAgICAgYnJlYWtcbiAgICBjYXNlIGBUZW1wb3JhbC5JbnN0YW50YDpcbiAgICAgIHNsb3RzLkVwb2NoTmFub3NlY29uZHMgPSBhY2Nlc3NHZXR0ZXIoXG4gICAgICAgIFRlbXBvcmFsLkluc3RhbnQsXG4gICAgICAgIGBlcG9jaE5hbm9zZWNvbmRzYCxcbiAgICAgICAgdmFsdWUsXG4gICAgICApXG4gICAgICBicmVha1xuICAgIGNhc2UgYFRlbXBvcmFsLlBsYWluRGF0ZWA6XG4gICAgICBzbG90cy5DYWxlbmRhciA9IGFjY2Vzc0dldHRlcihUZW1wb3JhbC5QbGFpbkRhdGUsIGBjYWxlbmRhcklkYCwgdmFsdWUpXG4gICAgICBzbG90cy5ZZWFyID0gYWNjZXNzR2V0dGVyKFRlbXBvcmFsLlBsYWluRGF0ZSwgYHllYXJgLCB2YWx1ZSlcbiAgICAgIHNsb3RzLk1vbnRoID0gYWNjZXNzR2V0dGVyKFRlbXBvcmFsLlBsYWluRGF0ZSwgYG1vbnRoYCwgdmFsdWUpXG4gICAgICBzbG90cy5EYXkgPSBhY2Nlc3NHZXR0ZXIoVGVtcG9yYWwuUGxhaW5EYXRlLCBgZGF5YCwgdmFsdWUpXG4gICAgICBicmVha1xuICAgIGNhc2UgYFRlbXBvcmFsLlBsYWluRGF0ZVRpbWVgOlxuICAgICAgc2xvdHMuQ2FsZW5kYXIgPSBhY2Nlc3NHZXR0ZXIoVGVtcG9yYWwuUGxhaW5EYXRlVGltZSwgYGNhbGVuZGFySWRgLCB2YWx1ZSlcbiAgICAgIHNsb3RzLlllYXIgPSBhY2Nlc3NHZXR0ZXIoVGVtcG9yYWwuUGxhaW5EYXRlVGltZSwgYHllYXJgLCB2YWx1ZSlcbiAgICAgIHNsb3RzLk1vbnRoID0gYWNjZXNzR2V0dGVyKFRlbXBvcmFsLlBsYWluRGF0ZVRpbWUsIGBtb250aGAsIHZhbHVlKVxuICAgICAgc2xvdHMuRGF5ID0gYWNjZXNzR2V0dGVyKFRlbXBvcmFsLlBsYWluRGF0ZVRpbWUsIGBkYXlgLCB2YWx1ZSlcbiAgICAgIHNsb3RzLkhvdXIgPSBhY2Nlc3NHZXR0ZXIoVGVtcG9yYWwuUGxhaW5EYXRlVGltZSwgYGhvdXJgLCB2YWx1ZSlcbiAgICAgIHNsb3RzLk1pbnV0ZSA9IGFjY2Vzc0dldHRlcihUZW1wb3JhbC5QbGFpbkRhdGVUaW1lLCBgbWludXRlYCwgdmFsdWUpXG4gICAgICBzbG90cy5TZWNvbmQgPSBhY2Nlc3NHZXR0ZXIoVGVtcG9yYWwuUGxhaW5EYXRlVGltZSwgYHNlY29uZGAsIHZhbHVlKVxuICAgICAgc2xvdHMuTWlsbGlzZWNvbmQgPSBhY2Nlc3NHZXR0ZXIoXG4gICAgICAgIFRlbXBvcmFsLlBsYWluRGF0ZVRpbWUsXG4gICAgICAgIGBtaWxsaXNlY29uZGAsXG4gICAgICAgIHZhbHVlLFxuICAgICAgKVxuICAgICAgc2xvdHMuTWljcm9zZWNvbmQgPSBhY2Nlc3NHZXR0ZXIoXG4gICAgICAgIFRlbXBvcmFsLlBsYWluRGF0ZVRpbWUsXG4gICAgICAgIGBtaWNyb3NlY29uZGAsXG4gICAgICAgIHZhbHVlLFxuICAgICAgKVxuICAgICAgc2xvdHMuTmFub3NlY29uZCA9IGFjY2Vzc0dldHRlcihcbiAgICAgICAgVGVtcG9yYWwuUGxhaW5EYXRlVGltZSxcbiAgICAgICAgYG5hbm9zZWNvbmRgLFxuICAgICAgICB2YWx1ZSxcbiAgICAgIClcbiAgICAgIGJyZWFrXG4gICAgY2FzZSBgVGVtcG9yYWwuUGxhaW5Nb250aERheWA6XG4gICAgICBzbG90cy5DYWxlbmRhciA9IGFjY2Vzc0dldHRlcihUZW1wb3JhbC5QbGFpbk1vbnRoRGF5LCBgY2FsZW5kYXJJZGAsIHZhbHVlKVxuICAgICAgc2xvdHMuTW9udGhDb2RlID0gYWNjZXNzR2V0dGVyKFRlbXBvcmFsLlBsYWluTW9udGhEYXksIGBtb250aENvZGVgLCB2YWx1ZSlcbiAgICAgIHNsb3RzLkRheSA9IGFjY2Vzc0dldHRlcihUZW1wb3JhbC5QbGFpbk1vbnRoRGF5LCBgZGF5YCwgdmFsdWUpXG4gICAgICBicmVha1xuICAgIGNhc2UgYFRlbXBvcmFsLlBsYWluVGltZWA6XG4gICAgICBzbG90cy5Ib3VyID0gYWNjZXNzR2V0dGVyKFRlbXBvcmFsLlBsYWluVGltZSwgYGhvdXJgLCB2YWx1ZSlcbiAgICAgIHNsb3RzLk1pbnV0ZSA9IGFjY2Vzc0dldHRlcihUZW1wb3JhbC5QbGFpblRpbWUsIGBtaW51dGVgLCB2YWx1ZSlcbiAgICAgIHNsb3RzLlNlY29uZCA9IGFjY2Vzc0dldHRlcihUZW1wb3JhbC5QbGFpblRpbWUsIGBzZWNvbmRgLCB2YWx1ZSlcbiAgICAgIHNsb3RzLk1pbGxpc2Vjb25kID0gYWNjZXNzR2V0dGVyKFRlbXBvcmFsLlBsYWluVGltZSwgYG1pbGxpc2Vjb25kYCwgdmFsdWUpXG4gICAgICBzbG90cy5NaWNyb3NlY29uZCA9IGFjY2Vzc0dldHRlcihUZW1wb3JhbC5QbGFpblRpbWUsIGBtaWNyb3NlY29uZGAsIHZhbHVlKVxuICAgICAgc2xvdHMuTmFub3NlY29uZCA9IGFjY2Vzc0dldHRlcihUZW1wb3JhbC5QbGFpblRpbWUsIGBuYW5vc2Vjb25kYCwgdmFsdWUpXG4gICAgICBicmVha1xuICAgIGNhc2UgYFRlbXBvcmFsLlBsYWluWWVhck1vbnRoYDpcbiAgICAgIHNsb3RzLkNhbGVuZGFyID0gYWNjZXNzR2V0dGVyKFxuICAgICAgICBUZW1wb3JhbC5QbGFpblllYXJNb250aCxcbiAgICAgICAgYGNhbGVuZGFySWRgLFxuICAgICAgICB2YWx1ZSxcbiAgICAgIClcbiAgICAgIHNsb3RzLlllYXIgPSBhY2Nlc3NHZXR0ZXIoVGVtcG9yYWwuUGxhaW5ZZWFyTW9udGgsIGB5ZWFyYCwgdmFsdWUpXG4gICAgICBzbG90cy5Nb250aCA9IGFjY2Vzc0dldHRlcihUZW1wb3JhbC5QbGFpblllYXJNb250aCwgYG1vbnRoYCwgdmFsdWUpXG4gICAgICBicmVha1xuICAgIGNhc2UgYFRlbXBvcmFsLlpvbmVkRGF0ZVRpbWVgOlxuICAgICAgc2xvdHMuQ2FsZW5kYXIgPSBhY2Nlc3NHZXR0ZXIoVGVtcG9yYWwuWm9uZWREYXRlVGltZSwgYGNhbGVuZGFySWRgLCB2YWx1ZSlcbiAgICAgIHNsb3RzLlRpbWVab25lID0gYWNjZXNzR2V0dGVyKFRlbXBvcmFsLlpvbmVkRGF0ZVRpbWUsIGB0aW1lWm9uZUlkYCwgdmFsdWUpXG4gICAgICBzbG90cy5FcG9jaE5hbm9zZWNvbmRzID0gYWNjZXNzR2V0dGVyKFxuICAgICAgICBUZW1wb3JhbC5ab25lZERhdGVUaW1lLFxuICAgICAgICBgZXBvY2hOYW5vc2Vjb25kc2AsXG4gICAgICAgIHZhbHVlLFxuICAgICAgKVxuICAgICAgYnJlYWtcbiAgfVxuXG4gIHJldHVybiBzbG90c1xufVxuXG5jb25zdCBhY2Nlc3NHZXR0ZXIgPSAoXG4gIGNsczogeyBwcm90b3R5cGU6IHVua25vd24gfSxcbiAga2V5OiBzdHJpbmcsXG4gIHZhbHVlOiBvYmplY3QsXG4pOiB1bmtub3duID0+IHtcbiAgZm9yIChcbiAgICBsZXQgcHJvdG90eXBlOiB1bmtub3duID0gY2xzLnByb3RvdHlwZTtcbiAgICBwcm90b3R5cGU7XG4gICAgcHJvdG90eXBlID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKHByb3RvdHlwZSlcbiAgKSB7XG4gICAgY29uc3QgZGVzY3JpcHRvciA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IocHJvdG90eXBlLCBrZXkpXG4gICAgaWYgKGRlc2NyaXB0b3IpIHtcbiAgICAgIHJldHVybiBkZXNjcmlwdG9yLmdldCEuY2FsbCh2YWx1ZSlcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHVuZGVmaW5lZFxufVxuXG5mdW5jdGlvbiogZW51bWVyYXRlT3duUHJvcGVydHlEaWZmcyhcbiAgbGVmdDogb2JqZWN0LFxuICByaWdodDogb2JqZWN0LFxuICBwYXRoOiBQYXRoLFxuICBzdGF0ZTogU3RhdGUsXG4pOiBHZW5lcmF0b3I8RGlmZj4ge1xuICBjb25zdCBsZWZ0S2V5cyA9IFJlZmxlY3Qub3duS2V5cyhsZWZ0KVxuICBjb25zdCByaWdodEtleXMgPSBSZWZsZWN0Lm93bktleXMocmlnaHQpXG5cbiAgY29uc3Qga2V5Q291bnQgPSBNYXRoLm1heChsZWZ0S2V5cy5sZW5ndGgsIHJpZ2h0S2V5cy5sZW5ndGgpXG4gIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCBrZXlDb3VudDsgaW5kZXgrKykge1xuICAgIGNvbnN0IGxlZnRLZXkgPSBtYXliZUNvbnZlcnRUb0luZGV4KGxlZnRLZXlzW2luZGV4XSlcbiAgICBjb25zdCByaWdodEtleSA9IG1heWJlQ29udmVydFRvSW5kZXgocmlnaHRLZXlzW2luZGV4XSlcblxuICAgIGlmIChsZWZ0S2V5ICE9PSByaWdodEtleSkge1xuICAgICAgeWllbGQge1xuICAgICAgICBraW5kOiBga2V5YCxcbiAgICAgICAgcGF0aDogWy4uLnBhdGhdLFxuICAgICAgICBpbmRleCxcbiAgICAgICAgbGVmdDogbGVmdEtleSxcbiAgICAgICAgcmlnaHQ6IHJpZ2h0S2V5LFxuICAgICAgfVxuICAgICAgY29udGludWVcbiAgICB9XG5cbiAgICBjb25zdCBrZXkgPSBsZWZ0S2V5IVxuICAgIGNvbnN0IGxlZnREZXNjcmlwdG9yID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihsZWZ0LCBrZXkpIVxuICAgIGNvbnN0IHJpZ2h0RGVzY3JpcHRvciA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IocmlnaHQsIGtleSkhXG4gICAgZm9yIChjb25zdCBkZXNjcmlwdG9yS2V5IG9mIFBST1BFUlRZX0RFU0NSSVBUT1JfS0VZUykge1xuICAgICAgeWllbGQqIGVudW1lcmF0ZURpZmZzKFxuICAgICAgICBsZWZ0RGVzY3JpcHRvcltkZXNjcmlwdG9yS2V5XSxcbiAgICAgICAgcmlnaHREZXNjcmlwdG9yW2Rlc2NyaXB0b3JLZXldLFxuICAgICAgICBbXG4gICAgICAgICAgLi4ucGF0aCxcbiAgICAgICAgICB7IGtpbmQ6IGBwcm9wZXJ0eWAsIGluZGV4LCBrZXkgfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBraW5kOiBgaW50ZXJuYWwtc2xvdGAgYXMgY29uc3QsXG4gICAgICAgICAgICBzbG90OiBkZXNjcmlwdG9yS2V5WzBdIS50b1VwcGVyQ2FzZSgpICsgZGVzY3JpcHRvcktleS5zbGljZSgxKSxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgICBzdGF0ZSxcbiAgICAgIClcbiAgICB9XG4gIH1cbn1cblxuY29uc3QgbWF5YmVDb252ZXJ0VG9JbmRleCA9IChcbiAga2V5OiBQcm9wZXJ0eUtleSB8IHVuZGVmaW5lZCxcbik6IFByb3BlcnR5S2V5IHwgdW5kZWZpbmVkID0+IHtcbiAgaWYgKGtleSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZFxuICB9XG5cbiAgaWYgKHR5cGVvZiBrZXkgIT09IGBzdHJpbmdgKSB7XG4gICAgcmV0dXJuIGtleVxuICB9XG5cbiAgY29uc3QgaW5kZXggPSBOdW1iZXIoa2V5KVxuICBpZiAoXG4gICAgTnVtYmVyLmlzSW50ZWdlcihpbmRleCkgJiZcbiAgICBpbmRleCA+PSAwICYmXG4gICAgaW5kZXggPD0gMiAqKiAzMiAtIDIgJiZcbiAgICBTdHJpbmcoaW5kZXgpID09PSBrZXlcbiAgKSB7XG4gICAgcmV0dXJuIGluZGV4XG4gIH1cblxuICByZXR1cm4ga2V5XG59XG5cbmNvbnN0IFBST1BFUlRZX0RFU0NSSVBUT1JfS0VZUyA9IFtcbiAgYGNvbmZpZ3VyYWJsZWAsXG4gIGBlbnVtZXJhYmxlYCxcbiAgYHdyaXRhYmxlYCxcbiAgYHZhbHVlYCxcbiAgYGdldGAsXG4gIGBzZXRgLFxuXSBhcyBjb25zdFxuXG5leHBvcnQgZGVmYXVsdCBzdHJpY3REaWZmXG4iXSwibWFwcGluZ3MiOiI0QkFpSUEsTUFBTSxFQUFBLENBQWMsRUFBaUIsS0FBQSxDQUFxQyxDQUN2RSxPQUFPLFVBQUEsSUFBaUIsRUFBZSxFQUFRLEVBQVEsR0FBSSxPQVF4RCxFQUFBLEtBQUEsQ0FDSixFQUFxQixJQUFJLElBQ3pCLEVBQXNCLElBQUksTUFHNUIsU0FBVSxFQUNSLEVBQ0EsRUFDQSxFQUNBLEdBRUEsR0FBSSxPQUFPLEdBQUcsRUFBTSxHQUNsQixPQUdGLE1BQU0sRUFBVyxFQUFZLEdBQ3ZCLEVBQVksRUFBWSxHQUM5QixHQUFJLElBQWEsRUFFZixpQkFETSxDQUFFLEtBQU0sT0FBUSxLQUFNLElBQUksR0FBTyxLQUFNLEVBQVUsTUFBTyxJQUloRSxJQUFLLEVBQVMsS0FBVSxFQUFTLEdBRS9CLGlCQURNLENBQUUsS0FBTSxRQUFTLEtBQU0sSUFBSSxHQUFPLE9BQU0sVUFJaEQsTUFBTSxFQUFvQixFQUFNLEVBQW9CLElBQUksR0FDbEQsRUFBcUIsRUFBTSxFQUFxQixJQUFJLEdBQ3RELEdBQXFCLEVBQ2xCLEVBQVcsRUFBbUIsVUFDM0IsQ0FDSixLQUFNLFlBQ04sS0FBTSxJQUFJLEdBQ1Ysb0JBQ0Esd0JBS04sRUFBTSxFQUFvQixJQUFJLEVBQU0sR0FDcEMsRUFBTSxFQUFxQixJQUFJLEVBQU8sU0FrRHhDLFVBQ0UsRUFDQSxFQUNBLEVBQ0EsRUFDQSxHQUVBLE1BQU0sRUFBWSxFQUFpQixFQUFNLEdBQ25DLEVBQWEsRUFBaUIsRUFBTSxHQUVwQyxFQUFRLElBQUksSUFBSSxJQUFJLE9BQU8sS0FBSyxNQUFlLE9BQU8sS0FBSyxLQUNqRSxJQUFLLE1BQU0sS0FBUSxRQUNWLEVBQ0wsRUFBVSxHQUNWLEVBQVcsR0FDWCxJQUFJLEVBQU0sQ0FBRSxLQUFNLGdCQUFpQixTQUNuQyxHQWhFRyxD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
package/license ADDED
@@ -0,0 +1,18 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Tomer Aberbach
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
6
+ associated documentation files (the "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
9
+ following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all copies or substantial
12
+ portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
15
+ LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
16
+ EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
18
+ USE OR OTHER DEALINGS IN THE SOFTWARE.
package/package.json ADDED
@@ -0,0 +1,73 @@
1
+ {
2
+ "name": "strict-diff",
3
+ "version": "0.0.1",
4
+ "author": {
5
+ "name": "Tomer Aberbach",
6
+ "email": "tomer@aberba.ch",
7
+ "url": "https://tomeraberba.ch"
8
+ },
9
+ "description": "Find any observable difference between two values.",
10
+ "keywords": [
11
+ "deep",
12
+ "diff",
13
+ "difference",
14
+ "equal",
15
+ "equals",
16
+ "equivalent",
17
+ "object",
18
+ "strict"
19
+ ],
20
+ "homepage": "https://github.com/TomerAberbach/strict-diff",
21
+ "repository": "TomerAberbach/strict-diff",
22
+ "bugs": {
23
+ "url": "https://github.com/TomerAberbach/strict-diff/issues"
24
+ },
25
+ "funding": {
26
+ "url": "https://github.com/sponsors/TomerAberbach"
27
+ },
28
+ "license": "MIT",
29
+ "files": [
30
+ "dist"
31
+ ],
32
+ "type": "module",
33
+ "sideEffects": false,
34
+ "engines": {
35
+ "node": ">= 22"
36
+ },
37
+ "exports": {
38
+ ".": {
39
+ "types": "./dist/index.d.mts",
40
+ "default": "./dist/index.js"
41
+ },
42
+ "./package.json": "./package.json"
43
+ },
44
+ "prettier": "@tomer/prettier-config",
45
+ "dependencies": {
46
+ "builtin-type": "^0.0.4"
47
+ },
48
+ "devDependencies": {
49
+ "@fast-check/vitest": "^0.3.0",
50
+ "@js-temporal/polyfill": "^0.5.1",
51
+ "@rollup/plugin-terser": "^1.0.0",
52
+ "@tomer/eslint-config": "^4.6.1",
53
+ "@tomer/prettier-config": "^4.0.0",
54
+ "@vitest/coverage-v8": "^4.0.18",
55
+ "eslint": "^9.39.2",
56
+ "jsdom": "^29.0.0",
57
+ "prettier": "^3.8.1",
58
+ "publint": "^0.3.18",
59
+ "rollup-plugin-tree-shakeable": "^2.0.0",
60
+ "tsdown": "^0.21.3",
61
+ "typescript": "^6.0.2",
62
+ "vitest": "^4.0.18"
63
+ },
64
+ "scripts": {
65
+ "format": "prettier --cache --write .",
66
+ "lint": "eslint --cache --cache-location node_modules/.cache/eslint/ --fix .",
67
+ "typecheck": "tsc --noEmit",
68
+ "test": "vitest",
69
+ "coverage": "vitest --coverage",
70
+ "bench": "vitest bench",
71
+ "build": "tsdown"
72
+ }
73
+ }
package/readme.md ADDED
@@ -0,0 +1,117 @@
1
+ <h1 align="center">
2
+ strict-diff
3
+ </h1>
4
+
5
+ <div align="center">
6
+ <a href="https://npmjs.org/package/strict-diff">
7
+ <img src="https://badgen.net/npm/v/strict-diff" alt="version" />
8
+ </a>
9
+ <a href="https://github.com/TomerAberbach/strict-diff/actions">
10
+ <img src="https://github.com/TomerAberbach/strict-diff/workflows/CI/badge.svg" alt="CI" />
11
+ </a>
12
+ <a href="https://unpkg.com/strict-diff/dist/index.js">
13
+ <img src="https://deno.bundlejs.com/?q=strict-diff&badge" alt="gzip size" />
14
+ </a>
15
+ <a href="https://unpkg.com/strict-diff/dist/index.js">
16
+ <img src="https://deno.bundlejs.com/?q=strict-diff&config={%22compression%22:{%22type%22:%22brotli%22}}&badge" alt="brotli size" />
17
+ </a>
18
+ <a href="https://github.com/sponsors/TomerAberbach">
19
+ <img src="https://img.shields.io/static/v1?label=Sponsor&message=%E2%9D%A4&logo=GitHub&color=%23fe8e86" alt="Sponsor" />
20
+ </a>
21
+ </div>
22
+
23
+ <div align="center">
24
+ Find any observable difference between two values.
25
+ </div>
26
+
27
+ ## Features
28
+
29
+ - **Strict:** Finds the most minuscule differences between values.
30
+ - **Structured:** Each diff has a structured path to the diff
31
+ - **Lazy:** Returns a lazy iterable over the diffs
32
+
33
+ ## Install
34
+
35
+ ```sh
36
+ $ npm i strict-diff
37
+ ```
38
+
39
+ ## Usage
40
+
41
+ ```js
42
+ import strictDiff from 'strict-diff'
43
+
44
+ // Primitive value diff
45
+ console.log([...strictDiff(1, 2)])
46
+ //=> [{ kind: 'value', path: [], left: 1, right: 2 }]
47
+
48
+ // Type diff
49
+ console.log([...strictDiff(null, undefined)])
50
+ //=> [{ kind: 'type', path: [], left: 'null', right: 'undefined' }]
51
+
52
+ // Object property value diff
53
+ console.log([...strictDiff({ a: 1 }, { a: 2 })])
54
+ //=> [
55
+ // {
56
+ // kind: 'value',
57
+ // path: [
58
+ // { kind: 'property', index: 0, key: 'a' },
59
+ // { kind: 'internal-slot', slot: 'Value' },
60
+ // ],
61
+ // left: 1,
62
+ // right: 2,
63
+ // },
64
+ // ]
65
+
66
+ // Object key diff
67
+ console.log([...strictDiff({ a: 1 }, { b: 1 })])
68
+ //=> [{ kind: 'key', path: [], index: 0, left: 'a', right: 'b' }]
69
+
70
+ // Property descriptor diff (non-writable vs writable)
71
+ const left = Object.defineProperty({}, `a`, {
72
+ value: 1,
73
+ writable: false,
74
+ enumerable: true,
75
+ configurable: true,
76
+ })
77
+ console.log([...strictDiff(left, { a: 1 })])
78
+ //=> [
79
+ // {
80
+ // kind: 'value',
81
+ // path: [
82
+ // { kind: 'property', index: 0, key: 'a' },
83
+ // { kind: 'internal-slot', slot: 'Writable' },
84
+ // ],
85
+ // left: false,
86
+ // right: true,
87
+ // },
88
+ // ]
89
+
90
+ // Lazily iterated
91
+ const diffs = strictDiff({ a: 1, b: 2 }, { a: 99, b: 99 })
92
+ const [firstDiff] = diffs
93
+ console.log(firstDiff)
94
+ //=> {
95
+ // kind: 'value',
96
+ // path: [
97
+ // { kind: 'property', index: 0, key: 'a' },
98
+ // { kind: 'internal-slot', slot: 'Value' },
99
+ // ],
100
+ // left: 1,
101
+ // right: 99,
102
+ // }
103
+ ```
104
+
105
+ See [the tests](./src/index.test.ts) for other example diffs.
106
+
107
+ ## Contributing
108
+
109
+ Stars are always welcome!
110
+
111
+ For bugs and feature requests,
112
+ [please create an issue](https://github.com/TomerAberbach/strict-diff/issues/new).
113
+
114
+ ## License
115
+
116
+ [MIT](https://github.com/TomerAberbach/strict-diff/blob/main/license) ©
117
+ [Tomer Aberbach](https://github.com/TomerAberbach)