From 601a924b07be5640525935a808cc2f42a1310440 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EF=BD=81=EF=BD=99=EF=BD=95=EF=BD=8D=EF=BD=89=C2=A0=20?= =?UTF-8?q?=EF=BD=99=EF=BD=95?= Date: Sun, 8 Oct 2017 21:33:54 +0000 Subject: [PATCH 1/2] Replace valueEquals.js with deep-equal Fix #167 --- client/recordUtil.js | 6 +- lib/valueEquals.js | 193 ------------------------------------------- package-lock.json | 5 +- package.json | 4 +- 4 files changed, 7 insertions(+), 201 deletions(-) delete mode 100644 lib/valueEquals.js diff --git a/client/recordUtil.js b/client/recordUtil.js index e0476c3..27160f5 100644 --- a/client/recordUtil.js +++ b/client/recordUtil.js @@ -1,9 +1,9 @@ 'use strict' +const deepEqual = require('deep-equal') const merge = require('lodash.merge') const proto = require('./constants/proto') const serializer = require('../lib/serializer') -const valueEquals = require('../lib/valueEquals') const {api} = require('../lib/api.proto.js') const syncTypes = require('../lib/syncTypes.js') @@ -144,7 +144,7 @@ const resolveRecordWithObject = (record, existingObject) => { return resolveSiteSettingsRecordWithObject(record, existingObject) } if (record.action === proto.actions.UPDATE) { - if (valueEquals(record[type], existingObject[type])) { + if (deepEqual(record[type], existingObject[type])) { // no-op return null } @@ -174,7 +174,7 @@ const resolveSiteSettingsRecordWithObject = (record, existingObject) => { if (record.action === proto.actions.UPDATE) { resolveField = (field) => { return !commonFields.includes(field) && - (!existingFields.has(field) || !valueEquals(existingObject[type][field], record[type][field])) + (!existingFields.has(field) || !deepEqual(existingObject[type][field], record[type][field])) } } else if (record.action === proto.actions.DELETE) { resolveField = (field) => { diff --git a/lib/valueEquals.js b/lib/valueEquals.js deleted file mode 100644 index 6ebd1a3..0000000 --- a/lib/valueEquals.js +++ /dev/null @@ -1,193 +0,0 @@ -/* valueEquals.js - - The MIT License (MIT) - - Copyright (c) 2013-2016, Reactive Sets - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*/ -'use strict' - -const reference_equals = (a, b) => { - var object_references = [] - - return (reference_equals = _reference_equals)(a, b) - - function _reference_equals (a, b) { - var l = object_references.length - - while (l--) { - if (object_references[ l-- ] === b) { return object_references[ l ] === a } - } - - object_references.push(a, b) - - return null - } -} - -const toString = Object.prototype.toString - - /* ----------------------------------------------------------------------------------------- - equals( a, b [, enforce_properties_order, cyclic] ) - - Returns true if a and b are deeply equal, false otherwise. - - Parameters: - - a (Any type): value to compare to b - - b (Any type): value compared to a - - Optional Parameters: - - enforce_properties_order (Boolean): true to check if Object properties are provided - in the same order between a and b - - - cyclic (Boolean): true to check for cycles in cyclic objects - - Implementation: - 'a' is considered equal to 'b' if all scalar values in a and b are strictly equal as - compared with operator '===' except for these two special cases: - - 0 === -0 but are not equal. - - NaN is not === to itself but is equal. - - RegExp objects are considered equal if they have the same lastIndex, i.e. both regular - expressions have matched the same number of times. - - Functions must be identical, so that they have the same closure context. - - "undefined" is a valid value, including in Objects - - 106 automated tests. - - Provide options for slower, less-common use cases: - - - Unless enforce_properties_order is true, if 'a' and 'b' are non-Array Objects, the - order of occurence of their attributes is considered irrelevant: - { a: 1, b: 2 } is considered equal to { b: 2, a: 1 } - - - Unless cyclic is true, Cyclic objects will throw: - RangeError: Maximum call stack size exceeded - */ -module.exports = (a, b, enforce_properties_order, cyclic) => { - return a === b // strick equality should be enough unless zero - && a !== 0 // because 0 === -0, requires test by _equals() - || _equals(a, b) // handles not strictly equal or zero values - - function _equals (a, b) { - // a and b have already failed test for strict equality or are zero - - var s, l, p, x, y - - // They should have the same toString() signature - if ((s = toString.call(a)) !== toString.call(b)) return false - - switch (s) { - default: // Boolean, Date, String - return a.valueOf() === b.valueOf() - - case '[object Number]': - // Converts Number instances into primitive values - // This is required also for NaN test bellow - a = +a - b = +b - - return a ? // a is Non-zero and Non-NaN - a === b - : // a is 0, -0 or NaN - a === a ? // a is 0 or -O - 1 / a === 1 / b // 1/0 !== 1/-0 because Infinity !== -Infinity - : b !== b // NaN, the only Number not equal to itself! - - // [object Number] - - case '[object RegExp]': - return a.source == b.source - && a.global == b.global - && a.ignoreCase == b.ignoreCase - && a.multiline == b.multiline - && a.lastIndex == b.lastIndex - - // [object RegExp] - - case '[object Function]': - return false // functions should be strictly equal because of closure context - // [object Function] - - case '[object Array]': - if (cyclic && (x = reference_equals(a, b)) !== null) return x // intentionally duplicated bellow for [object Object] - - if ((l = a.length) != b.length) return false - // Both have as many elements - - while (l--) { - if ((x = a[ l ]) === (y = b[ l ]) && x !== 0 || _equals(x, y)) continue - - return false - } - - return true - // [object Array] - - case '[object Object]': - if (cyclic && (x = reference_equals(a, b)) !== null) return x // intentionally duplicated from above for [object Array] - - l = 0 // counter of own properties - - if (enforce_properties_order) { - var properties = [] - - for (p in a) { - if (a.hasOwnProperty(p)) { - properties.push(p) - - if ((x = a[ p ]) === (y = b[ p ]) && x !== 0 || _equals(x, y)) continue - - return false - } - } - - // Check if 'b' has as the same properties as 'a' in the same order - for (p in b) { - if (b.hasOwnProperty(p) && properties[ l++ ] != p) { - return false - } - } - } else { - for (p in a) { - if (a.hasOwnProperty(p)) { - ++l - - if ((x = a[ p ]) === (y = b[ p ]) && x !== 0 || _equals(x, y)) continue - - return false - } - } - - // Check if 'b' has as not more own properties than 'a' - for (p in b) { - if (b.hasOwnProperty(p) && --l < 0) { - return false - } - } - } - - return true - // [object Object] - } // switch toString.call( a ) - } // _equals() -} // equals() diff --git a/package-lock.json b/package-lock.json index 51899c1..f01e936 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "brave-sync", - "version": "1.0.4", + "version": "1.4.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1380,8 +1380,7 @@ "deep-equal": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", - "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", - "dev": true + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=" }, "deep-extend": { "version": "0.4.2", diff --git a/package.json b/package.json index 30333d4..806171f 100644 --- a/package.json +++ b/package.json @@ -57,6 +57,7 @@ "config": "^1.24.0", "cors": "^2.8.1", "crc": "^3.4.4", + "deep-equal": "^1.0.1", "express": "^4.14.0", "lodash.merge": "^4.6.0", "protobufjs": "^6.8.0", @@ -72,8 +73,7 @@ "test/client/fixtures/*.js", "bundles/*.js", "client/polyfill/*.js", - "lib/api.proto.js", - "lib/valueEquals.js" + "lib/api.proto.js" ] } } From 9321c3a77c3e5f17f2483b95530f3aaf096cc2d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EF=BD=81=EF=BD=99=EF=BD=95=EF=BD=8D=EF=BD=89=C2=A0=20?= =?UTF-8?q?=EF=BD=99=EF=BD=95?= Date: Mon, 9 Oct 2017 03:50:58 +0000 Subject: [PATCH 2/2] v1.4.2 --- client/config.js | 2 +- package-lock.json | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/config.js b/client/config.js index 0d647c5..5623954 100644 --- a/client/config.js +++ b/client/config.js @@ -7,5 +7,5 @@ module.exports = { // 2-byte encryption nonce counter, rotated periodically nonceCounter: 0, // Sync library version, updated every brave/sync release - syncVersion: 'v1.4.1' + syncVersion: 'v1.4.2' } diff --git a/package-lock.json b/package-lock.json index f01e936..9c7b3c5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "brave-sync", - "version": "1.4.1", + "version": "1.4.2", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 806171f..8ef4723 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "brave-sync", - "version": "1.4.1", + "version": "1.4.2", "description": "Brave sync server and client", "main": "server/index.js", "scripts": {