From 11bfeaabfc72736a22e16cbbfe0ec75c2e7ed5ee Mon Sep 17 00:00:00 2001 From: Bryan Housel Date: Fri, 22 Mar 2019 17:14:41 -0400 Subject: [PATCH] Add browser-polyfills, remove lodash assign, compact, values (re: #6087) --- CONTRIBUTING.md | 18 ++++++++++++++---- data/index.js | 4 +--- modules/behavior/hash.js | 9 ++------- modules/core/difference.js | 3 +-- modules/core/graph.js | 7 +++---- modules/core/history.js | 11 +++-------- modules/id.js | 1 + modules/modes/select.js | 3 +-- modules/osm/changeset.js | 6 ++---- modules/presets/collection.js | 3 +-- modules/renderer/map.js | 6 ++---- modules/services/nominatim.js | 3 +-- modules/svg/areas.js | 3 +-- modules/svg/debug.js | 4 +--- modules/svg/midpoints.js | 19 ++++--------------- modules/svg/vertices.js | 9 +++------ modules/ui/feature_info.js | 21 +++++++++------------ modules/ui/intro/intro.js | 5 ++--- package.json | 1 + test/spec/renderer/features.js | 34 ++++++++++++---------------------- test/spec/spec_helpers.js | 27 --------------------------- 21 files changed, 65 insertions(+), 132 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0451a0279..955cae367 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -290,10 +290,21 @@ you're going to update the presets, [review the Presets README](/data/presets/RE ## JavaScript -iD uses ES5 syntax throughout the code, with one exception: -[ES6 modules](http://exploringjs.com/es6/ch_modules.html) using `import` and +iD uses ES5 syntax throughout the code, with the following exceptions: +- [ES6 modules](http://exploringjs.com/es6/ch_modules.html) using `import` and `export` constructs. These are processed by [Rollup.js](https://rollupjs.org/guide/en) and not present in the distributed iD bundle. +- Polyfills provided by [browser-polyfills](https://github.com/tiagomapmarques/browser-polyfills#what-does-it-have) + - `Promise` + - `fetch` + - `Map` + - `Set` + - `Array.find` + - `Array.findIndex` + - `Array.from` + - `Object.values` + - `Object.assign` + - `requestAnimationFrame (rAF)` ES5 syntax is required for: * IE11, which about 15-20% of our users still use @@ -307,8 +318,7 @@ only one difference: **4 space soft tabs always for JavaScript, not 2.** No aligned `=`, no aligned arguments, spaces are either indents or the 1 space between expressions. No hard tabs, ever. -JavaScript code should pass through [ESLint](http://eslint.org/) with no -warnings. +JavaScript code should pass through [ESLint](http://eslint.org/) with no warnings. ## HTML diff --git a/data/index.js b/data/index.js index 2cdc5a6b8..9f03b04a9 100644 --- a/data/index.js +++ b/data/index.js @@ -1,5 +1,3 @@ -import _values from 'lodash-es/values'; - export { wikipedia as dataWikipedia } from 'wmf-sitematrix'; export { dataAddressFormats } from './address-formats.json'; @@ -29,7 +27,7 @@ import whichPolygon from 'which-polygon'; // index the osm-community-index -var ociFeatureCollection = _values(ociFeatures).map(function(feature) { +var ociFeatureCollection = Object.values(ociFeatures).map(function(feature) { // workaround for which-polygon: only supports `properties`, not `id` // https://github.com/mapbox/which-polygon/pull/6 feature.properties = { diff --git a/modules/behavior/hash.js b/modules/behavior/hash.js index 72e20edf4..8a059a746 100644 --- a/modules/behavior/hash.js +++ b/modules/behavior/hash.js @@ -1,4 +1,3 @@ -import _assign from 'lodash-es/assign'; import _omit from 'lodash-es/omit'; import _throttle from 'lodash-es/throttle'; @@ -6,11 +5,7 @@ import { select as d3_select } from 'd3-selection'; import { geoSphericalDistance } from '../geo'; import { modeBrowse } from '../modes'; - -import { - utilQsString, - utilStringQs -} from '../util'; +import { utilQsString, utilStringQs } from '../util'; export function behaviorHash(context) { @@ -62,7 +57,7 @@ export function behaviorHash(context) { '/' + center[1].toFixed(precision) + '/' + center[0].toFixed(precision); - return '#' + utilQsString(_assign(q, newParams), true); + return '#' + utilQsString(Object.assign(q, newParams), true); }; diff --git a/modules/core/difference.js b/modules/core/difference.js index e897fb983..46f7fa895 100644 --- a/modules/core/difference.js +++ b/modules/core/difference.js @@ -1,7 +1,6 @@ import _difference from 'lodash-es/difference'; import _each from 'lodash-es/each'; import _isEqual from 'lodash-es/isEqual'; -import _values from 'lodash-es/values'; /* @@ -167,7 +166,7 @@ export function coreDifference(base, head) { } } - return _values(relevant); + return Object.values(relevant); }; diff --git a/modules/core/graph.js b/modules/core/graph.js index 20995570e..ace7e5fdd 100644 --- a/modules/core/graph.js +++ b/modules/core/graph.js @@ -1,4 +1,3 @@ -import _assign from 'lodash-es/assign'; import _difference from 'lodash-es/difference'; import _includes from 'lodash-es/includes'; import _without from 'lodash-es/without'; @@ -12,9 +11,9 @@ export function coreGraph(other, mutable) { if (other instanceof coreGraph) { var base = other.base(); - this.entities = _assign(Object.create(base.entities), other.entities); - this._parentWays = _assign(Object.create(base.parentWays), other._parentWays); - this._parentRels = _assign(Object.create(base.parentRels), other._parentRels); + this.entities = Object.assign(Object.create(base.entities), other.entities); + this._parentWays = Object.assign(Object.create(base.parentWays), other._parentWays); + this._parentRels = Object.assign(Object.create(base.parentRels), other._parentRels); } else { this.entities = Object.create({}); diff --git a/modules/core/history.js b/modules/core/history.js index ea4c7cdac..7ba8f8465 100644 --- a/modules/core/history.js +++ b/modules/core/history.js @@ -10,7 +10,6 @@ import _forEach from 'lodash-es/forEach'; import _map from 'lodash-es/map'; import _omit from 'lodash-es/omit'; import _reject from 'lodash-es/reject'; -import _values from 'lodash-es/values'; import _without from 'lodash-es/without'; import _uniq from 'lodash-es/uniq'; @@ -23,11 +22,7 @@ import { coreGraph } from './graph'; import { coreTree } from './tree'; import { osmEntity } from '../osm/entity'; import { uiLoading } from '../ui'; - -import { - utilRebind, - utilSessionMutex -} from '../util'; +import { utilRebind, utilSessionMutex } from '../util'; export function coreHistory(context) { @@ -472,8 +467,8 @@ export function coreHistory(context) { return JSON.stringify({ version: 3, - entities: _values(allEntities), - baseEntities: _values(baseEntities), + entities: Object.values(allEntities), + baseEntities: Object.values(baseEntities), stack: s, nextIDs: osmEntity.id.next, index: _index diff --git a/modules/id.js b/modules/id.js index ca50e84f9..df93f321e 100644 --- a/modules/id.js +++ b/modules/id.js @@ -1,2 +1,3 @@ +import 'browser-polyfills'; import * as iD from './index'; window.iD = iD; diff --git a/modules/modes/select.js b/modules/modes/select.js index 10703c4f6..f552eea5f 100644 --- a/modules/modes/select.js +++ b/modules/modes/select.js @@ -1,7 +1,6 @@ import _intersection from 'lodash-es/intersection'; import _map from 'lodash-es/map'; import _uniq from 'lodash-es/uniq'; -import _values from 'lodash-es/values'; import _without from 'lodash-es/without'; import { @@ -241,7 +240,7 @@ export function modeSelect(context, selectedIDs) { context.features().forceVisible(selectedIDs); - var operations = _without(_values(Operations), Operations.operationDelete) + var operations = _without(Object.values(Operations), Operations.operationDelete) .map(function(o) { return o(selectedIDs, context); }) .filter(function(o) { return o.available(); }); diff --git a/modules/osm/changeset.js b/modules/osm/changeset.js index 31deeeca3..e8e3e33a4 100644 --- a/modules/osm/changeset.js +++ b/modules/osm/changeset.js @@ -1,9 +1,7 @@ -import _compact from 'lodash-es/compact'; import _extend from 'lodash-es/extend'; import _filter from 'lodash-es/filter'; import _find from 'lodash-es/find'; import _map from 'lodash-es/map'; -import _values from 'lodash-es/values'; import { osmEntity } from './entity'; import { geoExtent } from '../geo'; @@ -106,7 +104,7 @@ _extend(osmChangeset.prototype, { while (processing.length > 0) { var next = processing[0], - deps = _filter(_compact(next.member.map(resolve)), isNew); + deps = _filter(next.member.map(resolve).filter(Boolean), isNew); if (deps.length === 0) { sorted[next['@id']] = next; processing.shift(); @@ -116,7 +114,7 @@ _extend(osmChangeset.prototype, { } } - changes.relation = _values(sorted); + changes.relation = Object.values(sorted); return changes; } diff --git a/modules/presets/collection.js b/modules/presets/collection.js index e5c9b426e..6876e645c 100644 --- a/modules/presets/collection.js +++ b/modules/presets/collection.js @@ -2,7 +2,6 @@ import _find from 'lodash-es/find'; import _findIndex from 'lodash-es/findIndex'; import _some from 'lodash-es/some'; import _uniq from 'lodash-es/uniq'; -import _values from 'lodash-es/values'; import _without from 'lodash-es/without'; import { utilEditDistance } from '../util/index'; @@ -108,7 +107,7 @@ export function presetCollection(collection) { // matches value to preset.tags values var leading_tag_values = searchable .filter(function(a) { - return _some(_without(_values(a.tags || {}), '*'), leading); + return _some(_without(Object.values(a.tags || {}), '*'), leading); }); var leading_suggestions = suggestions diff --git a/modules/renderer/map.js b/modules/renderer/map.js index ac74e91ce..88060c8ef 100644 --- a/modules/renderer/map.js +++ b/modules/renderer/map.js @@ -1,7 +1,5 @@ -import _compact from 'lodash-es/compact'; import _map from 'lodash-es/map'; import _throttle from 'lodash-es/throttle'; -import _values from 'lodash-es/values'; import { set as d3_set } from 'd3-collection'; import { dispatch as d3_dispatch } from 'd3-dispatch'; @@ -207,7 +205,7 @@ export function rendererMap(context) { } } }); - var data = _values(selectedAndParents); + var data = Object.values(selectedAndParents); var filter = function(d) { return d.id in selectedAndParents; }; data = context.features().filter(data, graph); @@ -279,7 +277,7 @@ export function rendererMap(context) { if (difference) { var complete = difference.complete(map.extent()); - data = _compact(_values(complete)); + data = Object.values(complete).filter(Boolean); filter = function(d) { return d.id in complete; }; features.clear(data); diff --git a/modules/services/nominatim.js b/modules/services/nominatim.js index 22b9d76cd..67c56af55 100644 --- a/modules/services/nominatim.js +++ b/modules/services/nominatim.js @@ -1,4 +1,3 @@ -import _assign from 'lodash-es/assign'; import _forEach from 'lodash-es/forEach'; import { json as d3_json } from 'd3-request'; @@ -63,7 +62,7 @@ export default { } var extent = geoExtent(location).padByMeters(200); - nominatimCache.insert(_assign(extent.bbox(), {data: result})); + nominatimCache.insert(Object.assign(extent.bbox(), {data: result})); callback(null, result); }); diff --git a/modules/svg/areas.js b/modules/svg/areas.js index 1cfbae252..2145024e8 100644 --- a/modules/svg/areas.js +++ b/modules/svg/areas.js @@ -1,5 +1,4 @@ import _map from 'lodash-es/map'; -import _values from 'lodash-es/values'; import { bisector as d3_bisector } from 'd3-array'; @@ -214,7 +213,7 @@ export function svgAreas(projection, context) { } } - areas = _values(areas).filter(function hasPath(a) { return path(a.entity); }); + areas = Object.values(areas).filter(function hasPath(a) { return path(a.entity); }); areas.sort(function areaSort(a, b) { return b.area - a.area; }); areas = _map(areas, 'entity'); diff --git a/modules/svg/debug.js b/modules/svg/debug.js index 8476991ff..b7497093c 100644 --- a/modules/svg/debug.js +++ b/modules/svg/debug.js @@ -1,5 +1,3 @@ -import _values from 'lodash-es/values'; - import { select as d3_select } from 'd3-selection'; import { data, dataImperial, dataDriveLeft } from '../../data'; @@ -94,7 +92,7 @@ export function svgDebug(projection, context) { var community = layer.selectAll('path.debug-community') - .data(showsCommunity ? _values(data.community.features) : []); + .data(showsCommunity ? Object.values(data.community.features) : []); community.exit() .remove(); diff --git a/modules/svg/midpoints.js b/modules/svg/midpoints.js index 6ed67823f..258818442 100644 --- a/modules/svg/midpoints.js +++ b/modules/svg/midpoints.js @@ -1,16 +1,5 @@ -import _values from 'lodash-es/values'; - -import { - svgPointTransform, - svgTagClasses -} from './index'; - -import { - geoAngle, - geoLineIntersection, - geoVecInterp, - geoVecLength -} from '../geo'; +import { svgPointTransform, svgTagClasses } from './index'; +import { geoAngle, geoLineIntersection, geoVecInterp, geoVecLength } from '../geo'; export function svgMidpoints(projection, context) { @@ -131,7 +120,7 @@ export function svgMidpoints(projection, context) { var groups = drawLayer.selectAll('.midpoint') .filter(midpointFilter) - .data(_values(midpoints), function(d) { return d.id; }); + .data(Object.values(midpoints), function(d) { return d.id; }); groups.exit() .remove(); @@ -170,7 +159,7 @@ export function svgMidpoints(projection, context) { // Draw touch targets.. touchLayer - .call(drawTargets, graph, _values(midpoints), midpointFilter); + .call(drawTargets, graph, Object.values(midpoints), midpointFilter); } return drawMidpoints; diff --git a/modules/svg/vertices.js b/modules/svg/vertices.js index 2d2abf2be..7163a82ed 100644 --- a/modules/svg/vertices.js +++ b/modules/svg/vertices.js @@ -1,6 +1,3 @@ -import _assign from 'lodash-es/assign'; -import _values from 'lodash-es/values'; - import { select as d3_select } from 'd3-selection'; import { geoScaleToZoom } from '../geo'; @@ -368,7 +365,7 @@ export function svgVertices(projection, context) { hovered: _currHover // hovered + siblings of hovered (render only in draw modes) }; - var all = _assign({}, (isMoving ? _currHover : {}), _currSelected, _currPersistent); + var all = Object.assign({}, (isMoving ? _currHover : {}), _currSelected, _currPersistent); // Draw the vertices.. // The filter function controls the scope of what objects d3 will touch (exit/enter/update) @@ -406,7 +403,7 @@ export function svgVertices(projection, context) { // note that drawVertices will add `_currSelected` automatically if needed.. var filter = function(d) { return d.id in _prevSelected; }; - drawVertices(selection, graph, _values(_prevSelected), filter, extent, false); + drawVertices(selection, graph, Object.values(_prevSelected), filter, extent, false); }; @@ -429,7 +426,7 @@ export function svgVertices(projection, context) { // note that drawVertices will add `_currHover` automatically if needed.. var filter = function(d) { return d.id in _prevHover; }; - drawVertices(selection, graph, _values(_prevHover), filter, extent, false); + drawVertices(selection, graph, Object.values(_prevHover), filter, extent, false); }; return drawVertices; diff --git a/modules/ui/feature_info.js b/modules/ui/feature_info.js index 8deec2291..db988d173 100644 --- a/modules/ui/feature_info.js +++ b/modules/ui/feature_info.js @@ -1,6 +1,3 @@ -import _compact from 'lodash-es/compact'; -import _map from 'lodash-es/map'; - import { event as d3_event } from 'd3-selection'; import { t } from '../util/locale'; @@ -10,15 +7,15 @@ import { tooltip } from '../util/tooltip'; export function uiFeatureInfo(context) { function update(selection) { - var features = context.features(), - stats = features.stats(), - count = 0, - hiddenList = _compact(_map(features.hidden(), function(k) { - if (stats[k]) { - count += stats[k]; - return String(stats[k]) + ' ' + t('feature.' + k + '.description'); - } - })); + var features = context.features(); + var stats = features.stats(); + var count = 0; + var hiddenList = features.hidden().map(function(k) { + if (stats[k]) { + count += stats[k]; + return String(stats[k]) + ' ' + t('feature.' + k + '.description'); + } + }).filter(Boolean); selection.html(''); diff --git a/modules/ui/intro/intro.js b/modules/ui/intro/intro.js index de03f835c..7f0bcb406 100644 --- a/modules/ui/intro/intro.js +++ b/modules/ui/intro/intro.js @@ -1,6 +1,5 @@ import _difference from 'lodash-es/difference'; import _uniq from 'lodash-es/uniq'; -import _values from 'lodash-es/values'; import { select as d3_select, @@ -86,7 +85,7 @@ export function uiIntro(context) { // Load semi-real data used in intro if (osm) { osm.toggle(false).reset(); } context.history().reset(); - context.history().merge(_values(coreGraph().load(introGraph).entities)); + context.history().merge(Object.values(coreGraph().load(introGraph).entities)); context.history().checkpoint('initial'); // Setup imagery @@ -165,7 +164,7 @@ export function uiIntro(context) { d3_selectAll('#map .layer-background').style('opacity', opacity); d3_selectAll('button.sidebar-toggle').classed('disabled', false); if (osm) { osm.toggle(true).reset().caches(caches); } - context.history().reset().merge(_values(baseEntities)); + context.history().reset().merge(Object.values(baseEntities)); context.background().baseLayerSource(background); overlays.forEach(function(d) { context.background().toggleOverlayLayer(d); }); if (history) { context.history().fromJSON(history, false); } diff --git a/package.json b/package.json index f0e5e25ff..602aeb18c 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "@mapbox/vector-tile": "^1.3.1", "@turf/bbox-clip": "^6.0.0", "alif-toolkit": "^1.2.5", + "browser-polyfills": "~1.5.0", "diacritics": "1.3.0", "fast-json-stable-stringify": "2.0.0", "lodash-es": "4.17.11", diff --git a/test/spec/renderer/features.js b/test/spec/renderer/features.js index 5ab0738a3..60397c930 100644 --- a/test/spec/renderer/features.js +++ b/test/spec/renderer/features.js @@ -1,24 +1,14 @@ -describe('iD.Features', function() { +describe('iD.rendererFeatures', function() { var dimensions = [1000, 1000]; var context, features; - function _values(obj) { - var result = []; - for (var k in obj) { - if (obj.hasOwnProperty(k)) { - result.push(obj[k]); - } - } - return result; - } - beforeEach(function() { context = iD.coreContext(); d3.select(document.createElement('div')) .attr('id', 'map') .call(context.map()); context.map().zoom(16); - features = iD.Features(context); + features = iD.rendererFeatures(context); }); describe('#keys', function() { @@ -74,7 +64,7 @@ describe('iD.Features', function() { iD.osmWay({id: 'boundary', tags: {boundary: 'administrative'}, version: 1}), iD.osmWay({id: 'fence', tags: {barrier: 'fence'}, version: 1}) ]); - var all = _values(graph.base().entities); + var all = Object.values(graph.base().entities); var stats; features.gatherStats(all, graph, dimensions); @@ -225,7 +215,7 @@ describe('iD.Features', function() { }) ]); - var all = _values(graph.base().entities); + var all = Object.values(graph.base().entities); function doMatch(ids) { @@ -463,7 +453,7 @@ describe('iD.Features', function() { var w = iD.osmWay({id: 'w', nodes: [a.id, b.id], tags: {highway: 'path'}, version: 1}); var graph = iD.coreGraph([a, b, w]); var geometry = a.geometry(graph); - var all = _values(graph.base().entities); + var all = Object.values(graph.base().entities); features.disable('paths'); features.gatherStats(all, graph, dimensions); @@ -491,7 +481,7 @@ describe('iD.Features', function() { version: 1 }); var graph = iD.coreGraph([outer, inner1, inner2, inner3, r]); - var all = _values(graph.base().entities); + var all = Object.values(graph.base().entities); features.disable('landuse'); features.gatherStats(all, graph, dimensions); @@ -508,7 +498,7 @@ describe('iD.Features', function() { var graph = iD.coreGraph([a, b]); var ageo = a.geometry(graph); var bgeo = b.geometry(graph); - var all = _values(graph.base().entities); + var all = Object.values(graph.base().entities); features.disable('points'); features.gatherStats(all, graph, dimensions); @@ -521,7 +511,7 @@ describe('iD.Features', function() { var a = iD.osmNode({id: 'a', version: 1}); var graph = iD.coreGraph([a]); var ageo = a.geometry(graph); - var all = _values(graph.base().entities); + var all = Object.values(graph.base().entities); features.disable('points'); features.gatherStats(all, graph, dimensions); @@ -539,7 +529,7 @@ describe('iD.Features', function() { graph.rebase([iD.osmNode({version: 1})], [graph]); } - all = _values(graph.base().entities); + all = Object.values(graph.base().entities); features.gatherStats(all, graph, dimensions); hidden = features.hidden(); autoHidden = features.autoHidden(); @@ -550,7 +540,7 @@ describe('iD.Features', function() { graph.rebase([iD.osmNode({version: 1})], [graph]); - all = _values(graph.base().entities); + all = Object.values(graph.base().entities); features.gatherStats(all, graph, dimensions); hidden = features.hidden(); autoHidden = features.autoHidden(); @@ -570,7 +560,7 @@ describe('iD.Features', function() { graph.rebase([iD.osmNode({version: 1})], [graph]); } - all = _values(graph.base().entities); + all = Object.values(graph.base().entities); features.gatherStats(all, graph, dimensions); hidden = features.hidden(); autoHidden = features.autoHidden(); @@ -581,7 +571,7 @@ describe('iD.Features', function() { graph.rebase([iD.osmNode({version: 1})], [graph]); - all = _values(graph.base().entities); + all = Object.values(graph.base().entities); features.gatherStats(all, graph, dimensions); hidden = features.hidden(); autoHidden = features.autoHidden(); diff --git a/test/spec/spec_helpers.js b/test/spec/spec_helpers.js index 1db452d4e..432a9ec11 100644 --- a/test/spec/spec_helpers.js +++ b/test/spec/spec_helpers.js @@ -44,30 +44,3 @@ if (!Object.getOwnPropertySymbols) { value: function() { return []; } }); } - -// Array.find polyfill (For PhantomJS / IE11) -// https://tc39.github.io/ecma262/#sec-array.prototype.find -if (!Array.prototype.find) { - Object.defineProperty(Array.prototype, 'find', { - value: function(predicate) { - if (this == null) { - throw new TypeError('"this" is null or not defined'); - } - var o = Object(this); - var len = o.length >>> 0; - if (typeof predicate !== 'function') { - throw new TypeError('predicate must be a function'); - } - var thisArg = arguments[1]; - var k = 0; - while (k < len) { - var kValue = o[k]; - if (predicate.call(thisArg, kValue, k, o)) { - return kValue; - } - k++; - } - return undefined; - } - }); -}