From 3673a7c7e758145a8377bd385db9bd949c11df85 Mon Sep 17 00:00:00 2001 From: Bryan Housel Date: Fri, 29 Mar 2019 17:18:40 -0400 Subject: [PATCH] Remove lodash cloneDeep (re #6087) - some were able to do a different approach (validations/almost_junction, and settings/*) - some were replaced with custom speedy cloners (in orthogonalize clonePoints and osm.js cloneNoteCache) - some just replaced with JSON.parse(JSON.stringify())) --- modules/actions/orthogonalize.js | 28 ++++++------- modules/services/osm.js | 33 +++++++++++---- modules/ui/fields/restrictions.js | 53 ++++-------------------- modules/ui/settings/custom_background.js | 8 ++-- modules/ui/settings/custom_data.js | 9 ++-- modules/validations/almost_junction.js | 28 ++++++------- 6 files changed, 70 insertions(+), 89 deletions(-) diff --git a/modules/actions/orthogonalize.js b/modules/actions/orthogonalize.js index 5d422b086..5bd3a505e 100644 --- a/modules/actions/orthogonalize.js +++ b/modules/actions/orthogonalize.js @@ -1,16 +1,7 @@ -import _cloneDeep from 'lodash-es/cloneDeep'; - import { actionDeleteNode } from './delete_node'; import { - geoVecAdd, - geoVecEqual, - geoVecInterp, - geoVecLength, - geoVecNormalize, - geoVecNormalizedDot, - geoVecProject, - geoVecScale, - geoVecSubtract + geoVecAdd, geoVecEqual, geoVecInterp, geoVecLength, geoVecNormalize, + geoVecNormalizedDot, geoVecProject, geoVecScale, geoVecSubtract } from '../geo'; @@ -92,10 +83,10 @@ export function actionOrthogonalize(wayID, projection, vertexID) { } // Orthogonalize the simplified shape - var bestPoints = _cloneDeep(simplified); - var originalPoints = _cloneDeep(simplified); - score = Infinity; + var bestPoints = clonePoints(simplified); + var originalPoints = clonePoints(simplified); + score = Infinity; for (i = 0; i < 1000; i++) { motions = simplified.map(calcMotion); @@ -104,7 +95,7 @@ export function actionOrthogonalize(wayID, projection, vertexID) { } var newScore = calcScore(simplified, isClosed); if (newScore < score) { - bestPoints = _cloneDeep(simplified); + bestPoints = clonePoints(simplified); score = newScore; } if (score < epsilon) { @@ -154,6 +145,13 @@ export function actionOrthogonalize(wayID, projection, vertexID) { return graph; + function clonePoints(array) { + return array.map(function(p) { + return { id: p.id, coord: [p.coord[0], p.coord[1]] }; + }); + } + + function calcMotion(point, i, array) { // don't try to move the endpoints of a non-closed way. if (!isClosed && (i === 0 || i === array.length - 1)) return [0, 0]; diff --git a/modules/services/osm.js b/modules/services/osm.js index 1ab1d43f3..1f57c9fc6 100644 --- a/modules/services/osm.js +++ b/modules/services/osm.js @@ -1,16 +1,14 @@ -import _cloneDeep from 'lodash-es/cloneDeep'; import _throttle from 'lodash-es/throttle'; -import rbush from 'rbush'; - import { dispatch as d3_dispatch } from 'd3-dispatch'; import { xml as d3_xml } from 'd3-request'; import osmAuth from 'osm-auth'; +import rbush from 'rbush'; + import { JXON } from '../util/jxon'; import { geoExtent, geoVecAdd } from '../geo'; import { osmEntity, osmNode, osmNote, osmRelation, osmWay } from '../osm'; - import { utilArrayChunk, utilArrayGroupBy, utilArrayUniq, utilRebind, utilIdleWorker, utilTiler, utilQsString @@ -994,11 +992,32 @@ export default { // This is used to save/restore the state when entering/exiting the walkthrough // Also used for testing purposes. caches: function(obj) { + function cloneDeep(source) { + return JSON.parse(JSON.stringify(source)); + } + + function cloneNoteCache(source) { + var target = {}; + Object.keys(source).forEach(function(k) { + if (k === 'rtree') { + target.rtree = rbush().fromJSON(source.rtree.toJSON()); + } else if (k === 'note') { + target.note = {}; + Object.keys(source.note).forEach(function(id) { + target.note[id] = osmNote(source.note[id]); + }); + } else { + target[k] = cloneDeep(source[k]); + } + }); + return target; + } + if (!arguments.length) { return { - tile: _cloneDeep(_tileCache), - note: _cloneDeep(_noteCache), - user: _cloneDeep(_userCache) + tile: cloneDeep(_tileCache), + note: cloneNoteCache(_noteCache), + user: cloneDeep(_userCache) }; } diff --git a/modules/ui/fields/restrictions.js b/modules/ui/fields/restrictions.js index a26007001..10d76d14b 100644 --- a/modules/ui/fields/restrictions.js +++ b/modules/ui/fields/restrictions.js @@ -1,52 +1,15 @@ -import _cloneDeep from 'lodash-es/cloneDeep'; - import { dispatch as d3_dispatch } from 'd3-dispatch'; - -import { - select as d3_select, - event as d3_event -} from 'd3-selection'; +import { select as d3_select, event as d3_event } from 'd3-selection'; import { t } from '../../util/locale'; import { actionRestrictTurn, actionUnrestrictTurn } from '../../actions'; import { behaviorBreathe } from '../../behavior'; - -import { - geoExtent, - geoRawMercator, - geoVecScale, - geoVecSubtract, - geoZoomToScale -} from '../../geo'; - -import { - osmIntersection, - osmInferRestriction, - osmTurn, - osmWay -} from '../../osm'; - -import { - svgLayers, - svgLines, - svgTurns, - svgVertices -} from '../../svg'; - -import { - utilDisplayName, - utilDisplayType, - utilEntitySelector, - utilFunctor, - utilRebind -} from '../../util'; - +import { geoExtent, geoRawMercator, geoVecScale, geoVecSubtract, geoZoomToScale } from '../../geo'; +import { osmIntersection, osmInferRestriction, osmTurn, osmWay } from '../../osm'; +import { svgLayers, svgLines, svgTurns, svgVertices } from '../../svg'; +import { utilDisplayName, utilDisplayType, utilEntitySelector, utilFunctor, utilRebind } from '../../util'; import { utilDetect } from '../../util/detect'; - -import { - utilGetDimensions, - utilSetDimensions -} from '../../util/dimensions'; +import { utilGetDimensions, utilSetDimensions } from '../../util/dimensions'; export function uiFieldRestrictions(field, context) { @@ -363,8 +326,8 @@ export function uiFieldRestrictions(field, context) { } else if (datum.restrictionID && !datum.only) { // NO -> ONLY var seen = {}; - var datumOnly = _cloneDeep(datum); - datumOnly.only = true; + var datumOnly = JSON.parse(JSON.stringify(datum)); // deep clone the datum + datumOnly.only = true; // but change this property restrictionType = restrictionType.replace(/^no/, 'only'); // Adding an ONLY restriction should destroy all other direct restrictions from the FROM towards the VIA. diff --git a/modules/ui/settings/custom_background.js b/modules/ui/settings/custom_background.js index 7af7365a5..413dd7f99 100644 --- a/modules/ui/settings/custom_background.js +++ b/modules/ui/settings/custom_background.js @@ -1,5 +1,3 @@ -import _cloneDeep from 'lodash-es/cloneDeep'; - import { dispatch as d3_dispatch } from 'd3-dispatch'; import { t } from '../../util/locale'; @@ -11,10 +9,14 @@ export function uiSettingsCustomBackground(context) { var dispatch = d3_dispatch('change'); function render(selection) { + // keep separate copies of original and current settings var _origSettings = { template: context.storage('background-custom-template') }; - var _currSettings = _cloneDeep(_origSettings); + var _currSettings = { + template: context.storage('background-custom-template') + }; + var example = 'https://{switch:a,b,c}.tile.openstreetmap.org/{zoom}/{x}/{y}.png'; var modal = uiConfirm(selection).okButton(); diff --git a/modules/ui/settings/custom_data.js b/modules/ui/settings/custom_data.js index 0ba28175f..097c8a037 100644 --- a/modules/ui/settings/custom_data.js +++ b/modules/ui/settings/custom_data.js @@ -1,5 +1,3 @@ -import _cloneDeep from 'lodash-es/cloneDeep'; - import { dispatch as d3_dispatch } from 'd3-dispatch'; import { event as d3_event } from 'd3-selection'; @@ -13,11 +11,16 @@ export function uiSettingsCustomData(context) { function render(selection) { var dataLayer = context.layers().layer('data'); + + // keep separate copies of original and current settings var _origSettings = { fileList: (dataLayer && dataLayer.fileList()) || null, url: context.storage('settings-custom-data-url') }; - var _currSettings = _cloneDeep(_origSettings); + var _currSettings = { + fileList: (dataLayer && dataLayer.fileList()) || null, + url: context.storage('settings-custom-data-url') + }; // var example = 'https://{switch:a,b,c}.tile.openstreetmap.org/{zoom}/{x}/{y}.png'; var modal = uiConfirm(selection).okButton(); diff --git a/modules/validations/almost_junction.js b/modules/validations/almost_junction.js index 8da908a11..cf7ab8ecb 100644 --- a/modules/validations/almost_junction.js +++ b/modules/validations/almost_junction.js @@ -1,12 +1,6 @@ -import _cloneDeep from 'lodash-es/cloneDeep'; import { - geoExtent, - geoLineIntersection, - geoMetersToLat, - geoMetersToLon, - geoSphericalDistance, - geoVecInterp, - geoHasSelfIntersections, + geoExtent, geoLineIntersection, geoMetersToLat, geoMetersToLon, + geoSphericalDistance, geoVecInterp, geoHasSelfIntersections, geoSphericalClosestNode } from '../geo'; @@ -50,24 +44,24 @@ export function validationAlmostJunction() { return true; } + function findConnectableEndNodesByExtension(way, graph, tree) { - var results = []; - if (way.isClosed()) return results; var nidFirst = way.nodes[0]; var nidLast = way.nodes[way.nodes.length - 1]; var nodeFirst = graph.entity(nidFirst); var nodeLast = graph.entity(nidLast); - - var testNodes; + var testNodes, index; if (isExtendableCandidate(nodeFirst, way, graph)) { var connNearFirst = canConnectByExtend(way, 0, graph, tree); if (connNearFirst !== null) { - testNodes = _cloneDeep(graph.childNodes(way)); - testNodes[0].loc = connNearFirst.cross_loc; + testNodes = graph.childNodes(way).slice(); // shallow copy + index = 0; // first + testNodes[index] = testNodes[index].move(connNearFirst.cross_loc); + // don't flag issue if connecting the ways would cause self-intersection if (!geoHasSelfIntersections(testNodes, nodeFirst.id)) { results.push({ @@ -83,8 +77,10 @@ export function validationAlmostJunction() { if (isExtendableCandidate(nodeLast, way, graph)) { var connNearLast = canConnectByExtend(way, way.nodes.length - 1, graph, tree); if (connNearLast !== null) { - testNodes = _cloneDeep(graph.childNodes(way)); - testNodes[testNodes.length-1].loc = connNearLast.cross_loc; + testNodes = graph.childNodes(way).slice(); // shallow copy + index = testNodes.length - 1; // last + testNodes[index] = testNodes[index].move(connNearFirst.cross_loc); + // don't flag issue if connecting the ways would cause self-intersection if (!geoHasSelfIntersections(testNodes, nodeLast.id)) { results.push({