Skip to content

Commit

Permalink
fix: extend is equal with file comparison logic #3911 (#3932)
Browse files Browse the repository at this point in the history
  • Loading branch information
logaretm committed Sep 19, 2022
1 parent 82d05db commit c7c806c
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 7 deletions.
1 change: 0 additions & 1 deletion package.json
Expand Up @@ -40,7 +40,6 @@
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-promise": "^5.1.0",
"eslint-plugin-standard": "^5.0.0",
"fast-deep-equal": "^3.1.3",
"filesize": "^8.0.7",
"flush-promises": "^1.0.2",
"fs-extra": "^10.1.0",
Expand Down
3 changes: 1 addition & 2 deletions packages/vee-validate/src/useField.ts
Expand Up @@ -13,10 +13,8 @@ import {
ComponentInternalInstance,
} from 'vue';
import { klona as deepCopy } from 'klona/full';
import isEqual from 'fast-deep-equal/es6';
import { validate as validateValue } from './validate';
import {
ValidationResult,
MaybeRef,
GenericValidateFunction,
YupValidator,
Expand All @@ -37,6 +35,7 @@ import {
isYupValidator,
applyModelModifiers,
withLatest,
isEqual,
} from './utils';
import { isCallable } from '../../shared';
import { FieldContextKey, FormContextKey, IS_ABSENT } from './symbols';
Expand Down
3 changes: 1 addition & 2 deletions packages/vee-validate/src/useFieldState.ts
@@ -1,8 +1,7 @@
import { computed, reactive, ref, Ref, unref, watch } from 'vue';
import isEqual from 'fast-deep-equal/es6';
import { FormContextKey } from './symbols';
import { FieldMeta, FieldState, MaybeRef } from './types';
import { getFromPath, injectWithSelf } from './utils';
import { getFromPath, injectWithSelf, isEqual } from './utils';

export interface StateSetterInit<TValue = unknown> extends FieldState<TValue> {
initialValue: TValue;
Expand Down
2 changes: 1 addition & 1 deletion packages/vee-validate/src/useForm.ts
Expand Up @@ -13,7 +13,6 @@ import {
markRaw,
watchEffect,
} from 'vue';
import isEqual from 'fast-deep-equal/es6';
import { klona as deepCopy } from 'klona/full';
import {
FieldMeta,
Expand Down Expand Up @@ -47,6 +46,7 @@ import {
debounceAsync,
isEmptyContainer,
withLatest,
isEqual,
} from './utils';
import { FormContextKey } from './symbols';
import { validateYupSchema, validateObjectSchema } from './validate';
Expand Down
78 changes: 78 additions & 0 deletions packages/vee-validate/src/utils/assertions.ts
Expand Up @@ -111,3 +111,81 @@ export function isEvent(evt: unknown): evt is Event {
export function isPropPresent(obj: Record<string, unknown>, prop: string) {
return prop in obj && obj[prop] !== IS_ABSENT;
}

/**
* Compares if two values are the same borrowed from:
* https://github.com/epoberezkin/fast-deep-equal
* We added a case for file matching since `Object.keys` doesn't work with Files.
* */
export function isEqual(a: any, b: any) {
if (a === b) return true;

if (a && b && typeof a === 'object' && typeof b === 'object') {
if (a.constructor !== b.constructor) return false;

// eslint-disable-next-line no-var
var length, i, keys;
if (Array.isArray(a)) {
length = a.length;
// eslint-disable-next-line eqeqeq
if (length != b.length) return false;
for (i = length; i-- !== 0; ) if (!isEqual(a[i], b[i])) return false;
return true;
}

if (a instanceof Map && b instanceof Map) {
if (a.size !== b.size) return false;
for (i of a.entries()) if (!b.has(i[0])) return false;
for (i of a.entries()) if (!isEqual(i[1], b.get(i[0]))) return false;
return true;
}

// We added this part for file comparison, arguably a little naive but should work for most cases.
// #3911
if (a instanceof File && b instanceof File) {
if (a.size !== b.size) return false;
if (a.name !== b.name) return false;
if (a.lastModified !== b.lastModified) return false;
if (a.type !== b.type) return false;

return true;
}

if (a instanceof Set && b instanceof Set) {
if (a.size !== b.size) return false;
for (i of a.entries()) if (!b.has(i[0])) return false;
return true;
}

if (ArrayBuffer.isView(a) && ArrayBuffer.isView(b)) {
length = (a as any).length;
// eslint-disable-next-line eqeqeq
if (length != (b as any).length) return false;
for (i = length; i-- !== 0; ) if ((a as any)[i] !== (b as any)[i]) return false;
return true;
}

if (a.constructor === RegExp) return a.source === b.source && a.flags === b.flags;
if (a.valueOf !== Object.prototype.valueOf) return a.valueOf() === b.valueOf();
if (a.toString !== Object.prototype.toString) return a.toString() === b.toString();

keys = Object.keys(a);
length = keys.length;
if (length !== Object.keys(b).length) return false;

for (i = length; i-- !== 0; ) if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false;

for (i = length; i-- !== 0; ) {
// eslint-disable-next-line no-var
var key = keys[i];

if (!isEqual(a[key], b[key])) return false;
}

return true;
}

// true if both NaN, false otherwise
// eslint-disable-next-line no-self-compare
return a !== a && b !== b;
}
2 changes: 1 addition & 1 deletion scripts/config.js
Expand Up @@ -50,7 +50,7 @@ function createConfig(pkg, format) {
}),
tsPlugin,
resolve({
dedupe: ['fast-deep-equal/es6', 'fast-deep-equal', 'klona', 'klona/full'],
dedupe: ['klona', 'klona/full'],
}),
commonjs(),
],
Expand Down

0 comments on commit c7c806c

Please sign in to comment.