From 50b1ab14e049ace9d3035f46833509e082fe28d3 Mon Sep 17 00:00:00 2001 From: dfahlander Date: Thu, 10 Jun 2021 23:51:43 +0200 Subject: [PATCH] Refactor _global and getObjectDiff to own modules --- src/classes/dexie/dexie-dom-dependencies.ts | 2 +- src/classes/dexie/dexie-static-props.ts | 4 +- src/classes/version/schema-helpers.ts | 3 +- src/functions/get-object-diff.ts | 51 ++++++++++++++++++ src/functions/utils.ts | 57 +-------------------- src/globals/global.ts | 6 +++ src/helpers/promise.js | 1 + src/hooks/hooks-middleware.ts | 3 +- 8 files changed, 68 insertions(+), 59 deletions(-) create mode 100644 src/functions/get-object-diff.ts create mode 100644 src/globals/global.ts diff --git a/src/classes/dexie/dexie-dom-dependencies.ts b/src/classes/dexie/dexie-dom-dependencies.ts index c589219c3..7851186f3 100644 --- a/src/classes/dexie/dexie-dom-dependencies.ts +++ b/src/classes/dexie/dexie-dom-dependencies.ts @@ -1,4 +1,4 @@ -import { _global } from '../../functions/utils'; +import { _global } from '../../globals/global'; import { DexieDOMDependencies } from '../../public/types/dexie-dom-dependencies'; export let domDeps: DexieDOMDependencies diff --git a/src/classes/dexie/dexie-static-props.ts b/src/classes/dexie/dexie-static-props.ts index a8ad1c359..c49041f6c 100644 --- a/src/classes/dexie/dexie-static-props.ts +++ b/src/classes/dexie/dexie-static-props.ts @@ -1,5 +1,7 @@ import { Dexie as _Dexie } from './dexie'; -import { props, derive, extend, override, getByKeyPath, setByKeyPath, delByKeyPath, shallowClone, deepClone, getObjectDiff, asap, _global } from '../../functions/utils'; +import { _global } from '../../globals/global'; +import { props, derive, extend, override, getByKeyPath, setByKeyPath, delByKeyPath, shallowClone, deepClone, asap } from '../../functions/utils'; +import { getObjectDiff } from "../../functions/get-object-diff"; import { fullNameExceptions } from '../../errors'; import { DexieConstructor } from '../../public/types/dexie-constructor'; import { getDatabaseNames } from '../../helpers/database-enumerator'; diff --git a/src/classes/version/schema-helpers.ts b/src/classes/version/schema-helpers.ts index 0bd15e452..1e1cc1eb8 100644 --- a/src/classes/version/schema-helpers.ts +++ b/src/classes/version/schema-helpers.ts @@ -1,6 +1,7 @@ import { Dexie } from '../dexie'; import { DbSchema } from '../../public/types/db-schema'; -import { setProp, keys, slice, _global, isArray, shallowClone, isAsyncFunction, defineProperty, getPropertyDescriptor } from '../../functions/utils'; +import { _global } from "../../globals/global"; +import { setProp, keys, slice, isArray, shallowClone, isAsyncFunction, defineProperty, getPropertyDescriptor } from '../../functions/utils'; import { Transaction } from '../transaction'; import { Version } from './version'; import Promise, { PSD, newScope, NativePromise, decrementExpectedAwaits, incrementExpectedAwaits } from '../../helpers/promise'; diff --git a/src/functions/get-object-diff.ts b/src/functions/get-object-diff.ts new file mode 100644 index 000000000..4501bd5ff --- /dev/null +++ b/src/functions/get-object-diff.ts @@ -0,0 +1,51 @@ +import { keys, hasOwn, toStringTag, intrinsicTypeNameSet, isArray } from "./utils"; + +export const getValueOf = (val:any, type: string) => + type === "Array" ? ''+val.map(v => getValueOf(v, toStringTag(v))) : + type === "ArrayBuffer" ? ''+new Uint8Array(val) : + type === "Date" ? val.getTime() : + ArrayBuffer.isView(val) ? ''+new Uint8Array(val.buffer) : + val; + + export function getObjectDiff(a, b, rv?, prfx?) { + // Compares objects a and b and produces a diff object. + rv = rv || {}; + prfx = prfx || ''; + keys(a).forEach(prop => { + if (!hasOwn(b, prop)) + rv[prfx+prop] = undefined; // Property removed + else { + var ap = a[prop], + bp = b[prop]; + if (typeof ap === 'object' && typeof bp === 'object' && ap && bp) + { + const apTypeName = toStringTag(ap); + const bpTypeName = toStringTag(bp); + + if (apTypeName === bpTypeName) { + if (intrinsicTypeNameSet[apTypeName] || isArray(ap)) { + // This is an intrinsic type. Don't go deep diffing it. + // Instead compare its value in best-effort: + // (Can compare real values of Date, ArrayBuffers and views) + if (getValueOf(ap, apTypeName) !== getValueOf(bp, bpTypeName)) { + rv[prfx + prop] = b[prop]; // Date / ArrayBuffer etc is of different value + } + } else { + // This is not an intrinsic object. Compare the it deeply: + getObjectDiff(ap, bp, rv, prfx + prop + "."); + } + } else { + rv[prfx + prop] = b[prop];// Property changed to other type + } + } else if (ap !== bp) + rv[prfx + prop] = b[prop];// Primitive value changed + } + }); + keys(b).forEach(prop => { + if (!hasOwn(a, prop)) { + rv[prfx+prop] = b[prop]; // Property added + } + }); + return rv; +} + diff --git a/src/functions/utils.ts b/src/functions/utils.ts index 821bf462c..a1bfe3ee6 100644 --- a/src/functions/utils.ts +++ b/src/functions/utils.ts @@ -1,10 +1,6 @@ -declare var global; +import { _global } from "../globals/global"; export const keys = Object.keys; export const isArray = Array.isArray; -const _global = - typeof self !== 'undefined' ? self : - typeof window !== 'undefined' ? window : - global; if (typeof Promise !== 'undefined' && !_global.Promise){ // In jsdom, this it can be the case that Promise is not put on the global object. // If so, we need to patch the global object for the rest of the code to work as expected. @@ -196,7 +192,7 @@ const intrinsicTypeNames = flatten([8,16,32,64].map(num=>["Int","Uint","Float"].map(t=>t+num+"Array"))) ).filter(t=>_global[t]); const intrinsicTypes = intrinsicTypeNames.map(t=>_global[t]); -const intrinsicTypeNameSet = arrayToObject(intrinsicTypeNames, x=>[x,true]); +export const intrinsicTypeNameSet = arrayToObject(intrinsicTypeNames, x=>[x,true]); let circularRefs: null | WeakMap = null; export function deepClone(any: T): T { @@ -236,55 +232,6 @@ export function toStringTag(o: Object) { return toString.call(o).slice(8, -1); } -export const getValueOf = (val:any, type: string) => - type === "Array" ? ''+val.map(v => getValueOf(v, toStringTag(v))) : - type === "ArrayBuffer" ? ''+new Uint8Array(val) : - type === "Date" ? val.getTime() : - ArrayBuffer.isView(val) ? ''+new Uint8Array(val.buffer) : - val; - - export function getObjectDiff(a, b, rv?, prfx?) { - // Compares objects a and b and produces a diff object. - rv = rv || {}; - prfx = prfx || ''; - keys(a).forEach(prop => { - if (!hasOwn(b, prop)) - rv[prfx+prop] = undefined; // Property removed - else { - var ap = a[prop], - bp = b[prop]; - if (typeof ap === 'object' && typeof bp === 'object' && ap && bp) - { - const apTypeName = toStringTag(ap); - const bpTypeName = toStringTag(bp); - - if (apTypeName === bpTypeName) { - if (intrinsicTypeNameSet[apTypeName] || isArray(ap)) { - // This is an intrinsic type. Don't go deep diffing it. - // Instead compare its value in best-effort: - // (Can compare real values of Date, ArrayBuffers and views) - if (getValueOf(ap, apTypeName) !== getValueOf(bp, bpTypeName)) { - rv[prfx + prop] = b[prop]; // Date / ArrayBuffer etc is of different value - } - } else { - // This is not an intrinsic object. Compare the it deeply: - getObjectDiff(ap, bp, rv, prfx + prop + "."); - } - } else { - rv[prfx + prop] = b[prop];// Property changed to other type - } - } else if (ap !== bp) - rv[prfx + prop] = b[prop];// Primitive value changed - } - }); - keys(b).forEach(prop => { - if (!hasOwn(a, prop)) { - rv[prfx+prop] = b[prop]; // Property added - } - }); - return rv; -} - // If first argument is iterable or array-like, return it as an array export const iteratorSymbol = typeof Symbol !== 'undefined' ? Symbol.iterator : diff --git a/src/globals/global.ts b/src/globals/global.ts new file mode 100644 index 000000000..78e5ce708 --- /dev/null +++ b/src/globals/global.ts @@ -0,0 +1,6 @@ +declare var global; +export const _global: any = + typeof globalThis !== 'undefined' ? globalThis : + typeof self !== 'undefined' ? self : + typeof window !== 'undefined' ? window : + global; diff --git a/src/helpers/promise.js b/src/helpers/promise.js index ed33fcc80..6633f3ebf 100644 --- a/src/helpers/promise.js +++ b/src/helpers/promise.js @@ -2,6 +2,7 @@ * Copyright (c) 2014-2017 David Fahlander * Apache License Version 2.0, January 2004, http://www.apache.org/licenses/LICENSE-2.0 */ +import { _global } from '../globals/global'; import {tryCatch, props, setProp, _global, getPropertyDescriptor, getArrayOf, extend, getProto} from '../functions/utils'; import {nop, callBoth, mirror} from '../functions/chaining-functions'; diff --git a/src/hooks/hooks-middleware.ts b/src/hooks/hooks-middleware.ts index e5bc2f29e..5af7416ca 100644 --- a/src/hooks/hooks-middleware.ts +++ b/src/hooks/hooks-middleware.ts @@ -10,7 +10,8 @@ import { DBCoreKeyRange } from "../public/types/dbcore"; import { nop } from '../functions/chaining-functions'; -import { getObjectDiff, hasOwn, setByKeyPath } from '../functions/utils'; +import { hasOwn, setByKeyPath } from '../functions/utils'; +import { getObjectDiff } from "../functions/get-object-diff"; import { PSD } from '../helpers/promise'; //import { LockableTableMiddleware } from '../dbcore/lockable-table-middleware'; import { getEffectiveKeys } from '../dbcore/get-effective-keys';