-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
cd6b31a
commit fef168f
Showing
10 changed files
with
288 additions
and
96 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
export function debounce(func, delay) { | ||
let debounceTimer = null; | ||
return (...args) => { | ||
if (debounceTimer) { | ||
clearTimeout(debounceTimer); | ||
} | ||
debounceTimer = window.setTimeout(() => func(...args), delay); | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
function isPlainObject(value) { | ||
return value?.constructor === Object; | ||
} | ||
export function isEqual(a, b) { | ||
if (Object.is(a, b)) return true; | ||
if (typeof a !== typeof b) return false; | ||
if (Array.isArray(a) && Array.isArray(b)) return isSameArray(a, b); | ||
if (a instanceof Date && b instanceof Date) | ||
return a.getTime() === b.getTime(); | ||
if (a instanceof RegExp && b instanceof RegExp) | ||
return a.toString() === b.toString(); | ||
if (isPlainObject(a) && isPlainObject(b)) return isSameObject(a, b); | ||
if (a instanceof ArrayBuffer && b instanceof ArrayBuffer) | ||
return dataViewsAreEqual(new DataView(a), new DataView(b)); | ||
if (a instanceof DataView && b instanceof DataView) | ||
return dataViewsAreEqual(a, b); | ||
if (isTypedArray(a) && isTypedArray(b)) { | ||
if (a.byteLength !== b.byteLength) return false; | ||
return isSameArray(a, b); | ||
} | ||
return false; | ||
} | ||
function isSameObject(a, b) { | ||
// check if the objects have the same keys | ||
const keys1 = Object.keys(a); | ||
const keys2 = Object.keys(b); | ||
if (!isEqual(keys1, keys2)) return false; | ||
// check if the values of each key in the objects are equal | ||
for (const key of keys1) { | ||
if (!isEqual(a[key], b[key])) return false; | ||
} | ||
// the objects are deeply equal | ||
return true; | ||
} | ||
function isSameArray(a, b) { | ||
if (a.length !== b.length) return false; | ||
return a.every((element, index) => isEqual(element, b[index])); | ||
} | ||
function dataViewsAreEqual(a, b) { | ||
if (a.byteLength !== b.byteLength) return false; | ||
for (let offset = 0; offset < a.byteLength; offset++) { | ||
if (a.getUint8(offset) !== b.getUint8(offset)) return false; | ||
} | ||
return true; | ||
} | ||
function isTypedArray(value) { | ||
return ArrayBuffer.isView(value) && !(value instanceof DataView); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
import { isEqual } from "../utils/isEqual"; | ||
|
||
describe("isEqual", () => { | ||
test("correctly compares against undefined", () => { | ||
expect(isEqual(undefined, undefined)).toBe(true); | ||
expect(isEqual(undefined, null)).toBe(false); | ||
expect(isEqual(undefined, 1)).toBe(false); | ||
expect(isEqual(undefined, "foo")).toBe(false); | ||
expect(isEqual(undefined, {})).toBe(false); | ||
expect(isEqual(undefined, [])).toBe(false); | ||
}); | ||
|
||
test("correct compares against nulls", () => { | ||
expect(isEqual(null, null)).toBe(true); | ||
expect(isEqual(null, 1)).toBe(false); | ||
expect(isEqual(null, "foo")).toBe(false); | ||
expect(isEqual(null, {})).toBe(false); | ||
expect(isEqual(null, [])).toBe(false); | ||
}); | ||
|
||
test("compares simple values", () => { | ||
expect(isEqual(1, 1)).toBe(true); | ||
expect(isEqual(1, 2)).toBe(false); | ||
expect(isEqual("foo", "foo")).toBe(true); | ||
expect(isEqual("foo", "bar")).toBe(false); | ||
}); | ||
|
||
test("compares objects", () => { | ||
expect(isEqual({}, {})).toBe(true); | ||
expect(isEqual({ foo: "bar" }, { foo: "bar" })).toBe(true); | ||
expect(isEqual({ foo: "bar" }, { foo: "baz" })).toBe(false); | ||
expect(isEqual({ foo: "bar" }, { bar: "baz" })).toBe(false); | ||
expect(isEqual({ foo: "bar" }, { foo: "bar", bar: "baz" })).toBe(false); | ||
}); | ||
|
||
test("deep compares objects", () => { | ||
expect(isEqual({ foo: { bar: "baz" } }, { foo: { bar: "baz" } })).toBe(true); | ||
expect(isEqual({ foo: { bar: "baz" } }, { foo: { bar: "qux" } })).toBe(false); | ||
expect(isEqual({ foo: { bar: "baz" } }, { foo: { baz: "qux" } })).toBe(false); | ||
expect(isEqual({ foo: { bar: "baz" } }, { foo: { bar: "baz", baz: "qux" } })).toBe(false); | ||
}); | ||
|
||
test("compares arrays", () => { | ||
expect(isEqual([], [])).toBe(true); | ||
expect(isEqual([1, 2, 3], [1, 2, 3])).toBe(true); | ||
expect(isEqual([1, 2, 3], [1, 2, 4])).toBe(false); | ||
expect(isEqual([1, 2, 3], [1, 2])).toBe(false); | ||
expect(isEqual([1, 2, 3], [1, 2, 3, 4])).toBe(false); | ||
}); | ||
|
||
test("compares maps", () => { | ||
const map1 = new Map(); | ||
map1.set("foo", "bar"); | ||
const map2 = new Map(); | ||
|
||
expect(isEqual(map1, map2)).toBe(false); | ||
}); | ||
|
||
test("compares dates", () => { | ||
expect(isEqual(new Date(1), new Date(1))).toBe(true); | ||
expect(isEqual(new Date(1), new Date(2))).toBe(false); | ||
}); | ||
|
||
test("compares nested arrays", () => { | ||
expect(isEqual([[1], [2], [3]], [[1], [2], [3]])).toBe(true); | ||
expect(isEqual([[1], [2], [3]], [[1], [2], [4]])).toBe(false); | ||
}); | ||
|
||
test("compares nested objects and arrays", () => { | ||
expect(isEqual({ a: { b: [1] } }, { a: { b: [1] } })).toBe(true); | ||
expect(isEqual({ a: { b: [1] } }, { a: { b: [2] } })).toBe(false); | ||
}); | ||
|
||
const testFunction = () => { return 1 }; | ||
test("functions", () => { | ||
expect(isEqual(() => { return 1 }, () => { return 2 })).toBe(false); | ||
expect(isEqual(testFunction, testFunction)).toBe(true); | ||
}); | ||
|
||
test("objects with functions", () => { | ||
expect(isEqual({ a: () => 1 }, { a: () => 1 })).toBe(false); | ||
expect(isEqual({ a: testFunction }, { a: testFunction })).toBe(true); | ||
}); | ||
|
||
test("regExp", () => { | ||
expect(isEqual(/a(.*)/, /a(.*)/)).toBe(true); | ||
expect(isEqual(/a/, /b.*/)).toBe(false); | ||
}); | ||
|
||
test("deepEquals with Error objects", () => { | ||
const error1 = new Error("test error"); | ||
const error2 = new Error("test error"); | ||
expect(isEqual(error1, error1)).toBe(true); | ||
expect(isEqual(error1, error2)).toBe(false); | ||
}); | ||
|
||
test("array buffers", () => { | ||
const buffer1 = new ArrayBuffer(2); | ||
const buffer1View = new Uint8Array(buffer1); | ||
buffer1View.set([42, 43]); | ||
|
||
const buffer2 = new ArrayBuffer(2); | ||
const buffer2View = new Uint8Array(buffer2); | ||
buffer2View.set([42, 43]); | ||
|
||
const buffer3 = new ArrayBuffer(2); | ||
const buffer3View = new Uint8Array(buffer3); | ||
buffer3View.set([42, 44]); | ||
|
||
const buffer4 = new ArrayBuffer(3); | ||
|
||
expect(isEqual(buffer1, buffer2)).toBe(true); | ||
expect(isEqual(buffer1, buffer3)).toBe(false); | ||
expect(isEqual(buffer1, buffer4)).toBe(false); | ||
}); | ||
|
||
test("typed arrays", () => { | ||
expect(isEqual(new Uint8Array([1, 2, 3]), new Uint8Array([1, 2, 3]))).toBe(true); | ||
expect(isEqual(new Uint8Array([1, 2, 3]), new Uint8Array([1, 2]))).toBe(false); | ||
expect(isEqual(new Uint8Array([1, 2, 3]), new Uint8Array([1, 2, 4]))).toBe(false); | ||
}); | ||
|
||
test("data views", () => { | ||
const buffer1 = new ArrayBuffer(2); | ||
const buffer2 = new ArrayBuffer(2); | ||
const buffer3 = new ArrayBuffer(3); | ||
|
||
const view1 = new DataView(buffer1); | ||
const view2 = new DataView(buffer2); | ||
const view3 = new DataView(buffer3); | ||
|
||
view1.setUint8(0, 42); | ||
view1.setUint8(1, 43); | ||
|
||
view2.setUint8(0, 42); | ||
view2.setUint8(1, 43); | ||
|
||
expect(isEqual(view1, view2)).toBe(true); | ||
expect(isEqual(view1, view3)).toBe(false); | ||
}); | ||
}); |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
export function debounce<F extends (...args: unknown[]) => unknown>( | ||
func: F, | ||
delay: number | ||
): (...args: Parameters<F>) => void { | ||
let debounceTimer: number | null = null; | ||
return (...args: Parameters<F>) => { | ||
if (debounceTimer) { | ||
clearTimeout(debounceTimer); | ||
} | ||
debounceTimer = window.setTimeout(() => func(...args), delay); | ||
}; | ||
} |
Oops, something went wrong.