From 6b7bfccc2d6950b06a8400bd3e62f034b77b90b8 Mon Sep 17 00:00:00 2001 From: Kyle Fazzari Date: Fri, 21 Jan 2022 09:55:08 -0800 Subject: [PATCH] format: stop relying on array properties There are numerous libraries out there (sugarjs, prototypejs) that extend the `Array` prototype. The `simplify` function in js-quantities relies on setting/checking properties on an array instance, which means that it's incompatible with such libraries. Add compatibility by using a separate object for keeping track of the counters instead of using properties on array instances. Fix #130. Signed-off-by: Kyle Fazzari --- build/quantities.js | 13 +++++++++---- build/quantities.mjs | 13 +++++++++---- package-lock.json | 2 +- spec/quantitiesSpec.js | 16 ++++++++++++++++ src/quantities/format.js | 7 +++++-- 5 files changed, 40 insertions(+), 11 deletions(-) diff --git a/build/quantities.js b/build/quantities.js index 77d61a0..55619b2 100644 --- a/build/quantities.js +++ b/build/quantities.js @@ -383,7 +383,7 @@ SOFTWARE. "" : [["Oe","oersted","oersteds"], 250.0 / Math.PI, "magnetism", [""], [""]], /* energy */ - "" : [["J","joule","Joule","joules"], 1.0, "energy", ["","",""], ["",""]], + "" : [["J","joule","Joule","joules","Joules"], 1.0, "energy", ["","",""], ["",""]], "" : [["erg","ergs"], 1e-7, "energy", ["","",""], ["",""]], "" : [["BTU","btu","BTUs"], 1055.056, "energy", ["","",""], ["",""]], "" : [["cal","calorie","calories"], 4.18400, "energy",["","",""], ["",""]], @@ -460,7 +460,9 @@ SOFTWARE. "" : [["doz","dz","dozen"],12.0,"prefix_only", [""]], "": [["%","percent"], 0.01, "prefix_only", ["<1>"]], "" : [["ppm"],1e-6, "prefix_only", ["<1>"]], - "" : [["ppt"],1e-9, "prefix_only", ["<1>"]], + "" : [["ppb"],1e-9, "prefix_only", ["<1>"]], + "" : [["ppt"],1e-12, "prefix_only", ["<1>"]], + "" : [["ppq"],1e-15, "prefix_only", ["<1>"]], "" : [["gr","gross"],144.0, "prefix_only", ["",""]], "" : [["dB","decibel","decibels"], 1.0, "logarithmic", [""]] }; @@ -1991,10 +1993,13 @@ SOFTWARE. function simplify(units) { // this turns ['s','m','s'] into ['s2','m'] + var counters = {}; var unitCounts = units.reduce(function(acc, unit) { - var unitCounter = acc[unit]; + var unitCounter = counters[unit]; if (!unitCounter) { - acc.push(unitCounter = acc[unit] = [unit, 0]); + unitCounter = [unit, 0]; + counters[unit] = unitCounter; + acc.push(unitCounter); } unitCounter[1]++; diff --git a/build/quantities.mjs b/build/quantities.mjs index 36c4f4a..8a0b637 100644 --- a/build/quantities.mjs +++ b/build/quantities.mjs @@ -377,7 +377,7 @@ var UNITS = { "" : [["Oe","oersted","oersteds"], 250.0 / Math.PI, "magnetism", [""], [""]], /* energy */ - "" : [["J","joule","Joule","joules"], 1.0, "energy", ["","",""], ["",""]], + "" : [["J","joule","Joule","joules","Joules"], 1.0, "energy", ["","",""], ["",""]], "" : [["erg","ergs"], 1e-7, "energy", ["","",""], ["",""]], "" : [["BTU","btu","BTUs"], 1055.056, "energy", ["","",""], ["",""]], "" : [["cal","calorie","calories"], 4.18400, "energy",["","",""], ["",""]], @@ -454,7 +454,9 @@ var UNITS = { "" : [["doz","dz","dozen"],12.0,"prefix_only", [""]], "": [["%","percent"], 0.01, "prefix_only", ["<1>"]], "" : [["ppm"],1e-6, "prefix_only", ["<1>"]], - "" : [["ppt"],1e-9, "prefix_only", ["<1>"]], + "" : [["ppb"],1e-9, "prefix_only", ["<1>"]], + "" : [["ppt"],1e-12, "prefix_only", ["<1>"]], + "" : [["ppq"],1e-15, "prefix_only", ["<1>"]], "" : [["gr","gross"],144.0, "prefix_only", ["",""]], "" : [["dB","decibel","decibels"], 1.0, "logarithmic", [""]] }; @@ -1985,10 +1987,13 @@ function getOutputNames(units) { function simplify(units) { // this turns ['s','m','s'] into ['s2','m'] + var counters = {}; var unitCounts = units.reduce(function(acc, unit) { - var unitCounter = acc[unit]; + var unitCounter = counters[unit]; if (!unitCounter) { - acc.push(unitCounter = acc[unit] = [unit, 0]); + unitCounter = [unit, 0]; + counters[unit] = unitCounter; + acc.push(unitCounter); } unitCounter[1]++; diff --git a/package-lock.json b/package-lock.json index d4a99b1..296d31f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "js-quantities", - "version": "1.7.5", + "version": "1.7.6", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/spec/quantitiesSpec.js b/spec/quantitiesSpec.js index 1aea55f..e9b893f 100644 --- a/spec/quantitiesSpec.js +++ b/spec/quantitiesSpec.js @@ -345,6 +345,22 @@ describe("js-quantities", function() { }); }); + describe("initialization with extensions to Array prototype", function() { + beforeEach(function() { + Array.prototype["min"] = Math.min; + }); + + afterEach(function() { + delete Array.prototype["min"]; + }); + + it("initialization should be agnostic to Array prototype extensions", function() { + var qty = Qty("100 gal/min"); + expect(qty.scalar).toEqual(100); + expect(qty.units()).toEqual("gal/min"); + }); + }); + describe("isCompatible", function() { it("should return true with compatible quantities", function() { var qty1 = Qty("1 m*kg/s"); diff --git a/src/quantities/format.js b/src/quantities/format.js index 4cb1d43..7e397e3 100644 --- a/src/quantities/format.js +++ b/src/quantities/format.js @@ -183,10 +183,13 @@ function getOutputNames(units) { function simplify(units) { // this turns ['s','m','s'] into ['s2','m'] + var counters = {}; var unitCounts = units.reduce(function(acc, unit) { - var unitCounter = acc[unit]; + var unitCounter = counters[unit]; if (!unitCounter) { - acc.push(unitCounter = acc[unit] = [unit, 0]); + unitCounter = [unit, 0]; + counters[unit] = unitCounter; + acc.push(unitCounter); } unitCounter[1]++;