diff --git a/src/web/js/cpo-ide-hooks.js b/src/web/js/cpo-ide-hooks.js
index c5406ee0..935cb6c9 100644
--- a/src/web/js/cpo-ide-hooks.js
+++ b/src/web/js/cpo-ide-hooks.js
@@ -32,13 +32,12 @@
   ],
   nativeRequires: [
     "cpo/cpo-builtin-modules",
-    "pyret-base/js/js-numbers",
   ],
   provides: {},
   theModule: function(runtime, namespace, uri,
                       compileLib, compileStructs, pyRepl, cpo,
                       runtimeLib, loadLib, cpoBuiltins, parsePyret,
-                      cpoModules, jsnums
+                      cpoModules
   ) {
     window.CPOIDEHooks = {
       runtime: runtime,
@@ -49,7 +48,7 @@
       compileStructs: compileStructs,
       compileLib: compileLib,
       cpoModules: cpoModules,
-      jsnums: jsnums
+      jsnums: runtime.jsnums
     };
     return runtime.makeModuleReturn({}, {});
   }
diff --git a/src/web/js/output-ui.js b/src/web/js/output-ui.js
index acba54a8..8dfbbe96 100644
--- a/src/web/js/output-ui.js
+++ b/src/web/js/output-ui.js
@@ -16,10 +16,10 @@
   provides: {},
   nativeRequires: [
     "pyret-base/js/runtime-util",
-    "pyret-base/js/js-numbers"
   ],
-  theModule: function(runtime, _, uri, parsePyret, errordisplayLib, srclocLib, astLib, imageLib, loadLib, util, jsnums) {
+  theModule: function(runtime, _, uri, parsePyret, errordisplayLib, srclocLib, astLib, imageLib, loadLib, util) {
 
+    var jsnums = runtime.jsnums;
     var image = runtime.getField(imageLib, "internal");
     var srcloc = runtime.getField(srclocLib, "values");
     var isSrcloc = runtime.getField(srcloc, "is-Srcloc");
@@ -1399,7 +1399,7 @@
           // after, and numerals to be repeated.
           var numr = num.numerator();
           var denr = num.denominator();
-          var decimal = jsnums.toRepeatingDecimal(numr, denr, runtime.NumberErrbacks);
+          var decimal = jsnums.toRepeatingDecimal(numr, denr);
           var prePointString = decimal[0];
           var postPointString = decimal[1];
           var decRpt = decimal[2];
diff --git a/src/web/js/trove/chart-lib.js b/src/web/js/trove/chart-lib.js
index 95461502..e18f32e7 100644
--- a/src/web/js/trove/chart-lib.js
+++ b/src/web/js/trove/chart-lib.js
@@ -4,7 +4,6 @@
     { 'import-type': 'builtin', 'name': 'image-lib' },
   ],
   nativeRequires: [
-    'pyret-base/js/js-numbers',
     'google-charts',
   ],
   provides: {
@@ -17,8 +16,9 @@
       'plot': "tany",
     }
   },
-  theModule: function (RUNTIME, NAMESPACE, uri, IMAGELIB, jsnums , google) {
-  'use strict';
+  theModule: function (RUNTIME, NAMESPACE, uri, IMAGELIB, google) {
+    'use strict';
+    var jsnums = RUNTIME.jsnums;
   // Load google library via editor.html to avoid loading issues
 
   function notImp(name) {
@@ -89,7 +89,7 @@
   function getPrettyNumToStringDigits(d) {
     // this accepts Pyret num
     return n =>
-      jsnums.toStringDigits(n, d, RUNTIME.NumberErrbacks).replace(/\.?0*$/, '');
+      jsnums.toStringDigits(n, d).replace(/\.?0*$/, '');
   }
 
   const prettyNumToStringDigits5 = getPrettyNumToStringDigits(5);
@@ -180,8 +180,7 @@
             xMaxC.removeClass('error-bg');
             xMaxC.addClass('ok-bg');
 
-            if (jsnums.greaterThanOrEqual(xMinVal, xMaxVal,
-                                          RUNTIME.NumberErrbacks)) {
+            if (jsnums.greaterThanOrEqual(xMinVal, xMaxVal)) {
               xMinC.addClass('error-bg');
               xMaxC.addClass('error-bg');
               xMinC.removeClass('ok-bg');
@@ -211,8 +210,7 @@
                     yMaxC.removeClass('error-bg');
                     yMaxC.addClass('ok-bg');
 
-                    if (jsnums.greaterThanOrEqual(xMinVal, xMaxVal,
-                                                  RUNTIME.NumberErrbacks)) {
+                    if (jsnums.greaterThanOrEqual(xMinVal, xMaxVal)) {
                       yMinC.addClass('error-bg');
                       yMaxC.addClass('error-bg');
                       yMinC.removeClass('ok-bg');
@@ -232,8 +230,7 @@
                         numSamplesC.addClass('ok-bg');
 
                         if (!isTrue(RUNTIME.num_is_integer(numSamplesVal)) ||
-                            jsnums.lessThanOrEqual(numSamplesVal, 1,
-                                                   RUNTIME.NumberErrbacks)) {
+                            jsnums.lessThanOrEqual(numSamplesVal, 1)) {
                           numSamplesC.addClass('error-bg');
                           numSamplesC.removeClass('ok-bg');
                           return null;
diff --git a/src/web/js/trove/d3-lib-list.js b/src/web/js/trove/d3-lib-list.js
index 46c88065..d74b1817 100644
--- a/src/web/js/trove/d3-lib-list.js
+++ b/src/web/js/trove/d3-lib-list.js
@@ -3,13 +3,13 @@
     { 'import-type': 'builtin', 'name': 'image-lib' },
   ],
   nativeRequires: [
-    'pyret-base/js/js-numbers',
     'd3'
   ],
   provides: {},
-  theModule: function (RUNTIME, NAMESPACE, uri, IMAGELIB, jsnums, d3) {
+  theModule: function (RUNTIME, NAMESPACE, uri, IMAGELIB, d3) {
   'use strict';
 
+    var jsnums = RUNTIME.jsnums;
   var IMAGE = RUNTIME.getField(IMAGELIB, "internal");
 
 
@@ -34,13 +34,13 @@
      * @return {jsnums -> jsnums}
      */
     return function (k) {
-      var oldDiff = jsnums.subtract(k, oldX, RUNTIME.NumberErrbacks);
-      var oldRange = jsnums.subtract(oldY, oldX, RUNTIME.NumberErrbacks);
-      var portion = jsnums.divide(oldDiff, oldRange, RUNTIME.NumberErrbacks);
-      var newRange = jsnums.subtract(newY, newX, RUNTIME.NumberErrbacks);
-      var newPortion = jsnums.multiply(portion, newRange, RUNTIME.NumberErrbacks);
-      var result = jsnums.add(newPortion, newX, RUNTIME.NumberErrbacks);
-      return toFixnum ? jsnums.toFixnum(result, RUNTIME.NumberErrbacks) : result;
+      var oldDiff = jsnums.subtract(k, oldX);
+      var oldRange = jsnums.subtract(oldY, oldX);
+      var portion = jsnums.divide(oldDiff, oldRange);
+      var newRange = jsnums.subtract(newY, newX);
+      var newPortion = jsnums.multiply(portion, newRange);
+      var result = jsnums.add(newPortion, newX);
+      return toFixnum ? jsnums.toFixnum(result) : result;
     };
   }
 
@@ -50,13 +50,13 @@
 
   function getPrettyNumToStringDigits(digits) {
     return function (num) {
-      return jsnums.toStringDigits(num, digits, RUNTIME.NumberErrbacks).replace(/\.?0*$/, '');
+      return jsnums.toStringDigits(num, digits).replace(/\.?0*$/, '');
     };
   }
 
   function between(b, a, c) {
-    return (jsnums.lessThanOrEqual(a, b, RUNTIME.NumberErrbacks) && jsnums.lessThanOrEqual(b, c, RUNTIME.NumberErrbacks)) ||
-           (jsnums.lessThanOrEqual(c, b, RUNTIME.NumberErrbacks) && jsnums.lessThanOrEqual(b, a, RUNTIME.NumberErrbacks));
+    return (jsnums.lessThanOrEqual(a, b) && jsnums.lessThanOrEqual(b, c)) ||
+           (jsnums.lessThanOrEqual(c, b) && jsnums.lessThanOrEqual(b, a));
   }
 
   function numMin(a, b) { /* ignore the rest */
diff --git a/src/web/js/trove/d3-lib.js b/src/web/js/trove/d3-lib.js
index 421bdd09..73b85596 100644
--- a/src/web/js/trove/d3-lib.js
+++ b/src/web/js/trove/d3-lib.js
@@ -3,13 +3,13 @@
     { 'import-type': 'builtin', 'name': 'image-lib' },
   ],
   nativeRequires: [
-    'pyret-base/js/js-numbers',
     'd3'
   ],
   provides: {},
-  theModule: function (RUNTIME, NAMESPACE, uri, IMAGELIB, jsnums, d3) {
+  theModule: function (RUNTIME, NAMESPACE, uri, IMAGELIB, d3) {
   'use strict';
 
+    var jsnums = RUNTIME.jsnums;
   var IMAGE = RUNTIME.getField(IMAGELIB, "internal");
 
   function assert(val, msg) {
@@ -33,13 +33,13 @@
      * @return {jsnums -> jsnums}
      */
     return function (k) {
-      var oldDiff = jsnums.subtract(k, oldX, RUNTIME.NumberErrbacks);
-      var oldRange = jsnums.subtract(oldY, oldX, RUNTIME.NumberErrbacks);
-      var portion = jsnums.divide(oldDiff, oldRange, RUNTIME.NumberErrbacks);
-      var newRange = jsnums.subtract(newY, newX, RUNTIME.NumberErrbacks);
-      var newPortion = jsnums.multiply(portion, newRange, RUNTIME.NumberErrbacks);
-      var result = jsnums.add(newPortion, newX, RUNTIME.NumberErrbacks);
-      return toFixnum ? jsnums.toFixnum(result, RUNTIME.NumberErrbacks) : result;
+      var oldDiff = jsnums.subtract(k, oldX);
+      var oldRange = jsnums.subtract(oldY, oldX);
+      var portion = jsnums.divide(oldDiff, oldRange);
+      var newRange = jsnums.subtract(newY, newX);
+      var newPortion = jsnums.multiply(portion, newRange);
+      var result = jsnums.add(newPortion, newX);
+      return toFixnum ? jsnums.toFixnum(result) : result;
     };
   }
 
@@ -49,13 +49,13 @@
 
   function getPrettyNumToStringDigits(digits) {
     return function (num) {
-      return jsnums.toStringDigits(num, digits, RUNTIME.NumberErrbacks).replace(/\.?0*$/, '');
+      return jsnums.toStringDigits(num, digits).replace(/\.?0*$/, '');
     };
   }
 
   function between(b, a, c) {
-    return (jsnums.lessThanOrEqual(a, b, RUNTIME.NumberErrbacks) && jsnums.lessThanOrEqual(b, c, RUNTIME.NumberErrbacks)) ||
-           (jsnums.lessThanOrEqual(c, b, RUNTIME.NumberErrbacks) && jsnums.lessThanOrEqual(b, a, RUNTIME.NumberErrbacks));
+    return (jsnums.lessThanOrEqual(a, b) && jsnums.lessThanOrEqual(b, c)) ||
+           (jsnums.lessThanOrEqual(c, b) && jsnums.lessThanOrEqual(b, a));
   }
 
   function numMin(a, b) { /* ignore the rest */
diff --git a/src/web/js/trove/plot-lib-list.js b/src/web/js/trove/plot-lib-list.js
index c285c11a..05672e0f 100644
--- a/src/web/js/trove/plot-lib-list.js
+++ b/src/web/js/trove/plot-lib-list.js
@@ -3,7 +3,6 @@
     { 'import-type': 'builtin', 'name': 'd3-lib-list' },
   ],
   nativeRequires: [
-    'pyret-base/js/js-numbers',
     'd3',
     'd3-tip'
   ],
@@ -17,8 +16,9 @@
       'box-chart': "tany"
     }
   },
-  theModule: function (RUNTIME, NAMESPACE, uri, CLIB, jsnums, d3, D3TIP) {
-  'use strict';
+  theModule: function (RUNTIME, NAMESPACE, uri, CLIB, d3, D3TIP) {
+    'use strict';
+    var jsnums = RUNTIME.jsnums;
   var gf = RUNTIME.getField,
       cases = RUNTIME.ffi.cases;
   var libNum =       CLIB.libNum,
@@ -69,7 +69,7 @@
     function getAxisConf(aMin, aMax) {
       const conf = {},
             scaler = libNum.scaler(aMin, aMax, 0, 1, false),
-            pos = jsnums.toFixnum(scaler(0), RUNTIME.NumberErrbacks);
+            pos = jsnums.toFixnum(scaler(0));
 
       if (0 <= pos && pos <= 1) {
         conf.bold = true;
@@ -285,7 +285,7 @@
               xMaxC.removeClass('error-bg');
               xMaxC.addClass('ok-bg');
 
-              if (jsnums.greaterThanOrEqual(xMin_val, xMax_val, RUNTIME.NumberErrbacks)) {
+              if (jsnums.greaterThanOrEqual(xMin_val, xMax_val)) {
                 xMinC.addClass('error-bg');
                 xMaxC.addClass('error-bg');
                 xMinC.removeClass('ok-bg');
@@ -313,7 +313,7 @@
                       yMaxC.removeClass('error-bg');
                       yMaxC.addClass('ok-bg');
 
-                      if (jsnums.greaterThanOrEqual(xMin_val, xMax_val, RUNTIME.NumberErrbacks)) {
+                      if (jsnums.greaterThanOrEqual(xMin_val, xMax_val)) {
                         yMinC.addClass('error-bg');
                         yMaxC.addClass('error-bg');
                         yMinC.removeClass('ok-bg');
@@ -332,7 +332,7 @@
                           numSamplesC.addClass('ok-bg');
 
                           if (RUNTIME.isPyretFalse(RUNTIME.num_is_integer(numSamples_val)) ||
-                              jsnums.lessThanOrEqual(numSamples_val, 1, RUNTIME.NumberErrbacks)) {
+                              jsnums.lessThanOrEqual(numSamples_val, 1)) {
                             numSamplesC.addClass('error-bg');
                             numSamplesC.removeClass('ok-bg');
                             return null;
@@ -372,9 +372,9 @@
       if (newWindow === null) { return; }
       var xMin_val = newWindow['_x-min'];
       var xMax_val = newWindow['_x-max'];
-      var move = jsnums.divide(jsnums.subtract(xMax_val, xMin_val, RUNTIME.NumberErrbacks), 10, RUNTIME.NumberErrbacks);
-      xMinC.val(prettyNumToStringDigits20(jsnums.subtract(xMin_val, move, RUNTIME.NumberErrbacks)));
-      xMaxC.val(prettyNumToStringDigits20(jsnums.subtract(xMax_val, move, RUNTIME.NumberErrbacks)));
+      var move = jsnums.divide(jsnums.subtract(xMax_val, xMin_val), 10);
+      xMinC.val(prettyNumToStringDigits20(jsnums.subtract(xMin_val, move)));
+      xMaxC.val(prettyNumToStringDigits20(jsnums.subtract(xMax_val, move)));
     }));
     controller.append($('', {
       text: '⇨',
@@ -388,8 +388,8 @@
       var xMin_val = newWindow['_x-min'];
       var xMax_val = newWindow['_x-max'];
       var move = jsnums.divide(jsnums.subtract(xMax_val, xMin_val), 10);
-      xMinC.val(prettyNumToStringDigits20(jsnums.add(xMin_val, move, RUNTIME.NumberErrbacks)));
-      xMaxC.val(prettyNumToStringDigits20(jsnums.add(xMax_val, move, RUNTIME.NumberErrbacks)));
+      xMinC.val(prettyNumToStringDigits20(jsnums.add(xMin_val, move)));
+      xMaxC.val(prettyNumToStringDigits20(jsnums.add(xMax_val, move)));
     }));
     controller.append($('', {
       text: '⇩',
@@ -403,8 +403,8 @@
       var yMin_val = newWindow['_y-min'];
       var yMax_val = newWindow['_y-max'];
       var move = jsnums.divide(jsnums.subtract(yMax_val, yMin_val), 10);
-      yMinC.val(prettyNumToStringDigits20(jsnums.subtract(yMin_val, move, RUNTIME.NumberErrbacks)));
-      yMaxC.val(prettyNumToStringDigits20(jsnums.subtract(yMax_val, move, RUNTIME.NumberErrbacks)));
+      yMinC.val(prettyNumToStringDigits20(jsnums.subtract(yMin_val, move)));
+      yMaxC.val(prettyNumToStringDigits20(jsnums.subtract(yMax_val, move)));
     }));
     controller.append($('', {
       text: '⇧',
@@ -418,8 +418,8 @@
       var yMin_val = newWindow['_y-min'];
       var yMax_val = newWindow['_y-max'];
       var move = jsnums.divide(jsnums.subtract(yMax_val, yMin_val), 10);
-      yMinC.val(prettyNumToStringDigits20(jsnums.add(yMin_val, move, RUNTIME.NumberErrbacks)));
-      yMaxC.val(prettyNumToStringDigits20(jsnums.add(yMax_val, move, RUNTIME.NumberErrbacks)));
+      yMinC.val(prettyNumToStringDigits20(jsnums.add(yMin_val, move)));
+      yMaxC.val(prettyNumToStringDigits20(jsnums.add(yMax_val, move)));
     }));
 
     var redraw = $('', {
@@ -469,10 +469,10 @@
         var cy = pixelToY(coord[1]);
         var radiusY = jsnums.subtract(yMax, yMin);
 
-        xMinC.val(prettyNumToStringDigits20(jsnums.subtract(cx, radiusX, RUNTIME.NumberErrbacks)));
-        xMaxC.val(prettyNumToStringDigits20(jsnums.add(cx, radiusX, RUNTIME.NumberErrbacks)));
-        yMinC.val(prettyNumToStringDigits20(jsnums.subtract(cy, radiusY, RUNTIME.NumberErrbacks)));
-        yMaxC.val(prettyNumToStringDigits20(jsnums.add(cy, radiusY, RUNTIME.NumberErrbacks)));
+        xMinC.val(prettyNumToStringDigits20(jsnums.subtract(cx, radiusX)));
+        xMaxC.val(prettyNumToStringDigits20(jsnums.add(cx, radiusX)));
+        yMinC.val(prettyNumToStringDigits20(jsnums.subtract(cy, radiusY)));
+        yMaxC.val(prettyNumToStringDigits20(jsnums.add(cy, radiusY)));
 
       })
       .on('mousedown', function () {
@@ -619,16 +619,16 @@
     var yMax = gf(windowOptions, '_y-max');
 
     function inBound(p) {
-      return jsnums.lessThanOrEqual(xMin, p[0], RUNTIME.NumberErrbacks) &&
-             jsnums.lessThanOrEqual(p[0], xMax, RUNTIME.NumberErrbacks) &&
-             jsnums.lessThanOrEqual(yMin, p[1], RUNTIME.NumberErrbacks) &&
-             jsnums.lessThanOrEqual(p[1], yMax, RUNTIME.NumberErrbacks);
+      return jsnums.lessThanOrEqual(xMin, p[0]) &&
+             jsnums.lessThanOrEqual(p[0], xMax) &&
+             jsnums.lessThanOrEqual(yMin, p[1]) &&
+             jsnums.lessThanOrEqual(p[1], yMax);
     }
 
     function dist(a, b) {
       return jsnums.add(
-        jsnums.sqr(jsnums.subtract(a[0], b[0], RUNTIME.NumberErrbacks)),
-        jsnums.sqr(jsnums.subtract(a[1], b[1], RUNTIME.NumberErrbacks)), RUNTIME.NumberErrbacks);
+        jsnums.sqr(jsnums.subtract(a[0], b[0])),
+        jsnums.sqr(jsnums.subtract(a[1], b[1])));
     }
 
     function nearest(candidates, origin) {
@@ -636,7 +636,7 @@
       var optimal = null;
       candidates.forEach(function (candidate) {
         var distance = dist(candidate, origin);
-        if (optimal === null || jsnums.lessThan(distance, optimal, RUNTIME.NumberErrbacks)) {
+        if (optimal === null || jsnums.lessThan(distance, optimal)) {
           optimal = distance;
           ans = candidate;
         }
@@ -645,7 +645,7 @@
     }
 
     function equal(a, b) {
-      return jsnums.lessThanOrEqual(a, b, RUNTIME.NumberErrbacks) && jsnums.lessThanOrEqual(b, a, RUNTIME.NumberErrbacks);
+      return jsnums.lessThanOrEqual(a, b) && jsnums.lessThanOrEqual(b, a);
     }
 
     function findPointOnEdge(near, far) {
@@ -677,15 +677,15 @@
         x = (y - c) / m         [4]   [rewrite 3]
         */
 
-        var m = jsnums.divide(jsnums.subtract(near[1], far[1], RUNTIME.NumberErrbacks), jsnums.subtract(near[0], far[0], RUNTIME.NumberErrbacks));
-        var c = jsnums.subtract(near[1], jsnums.multiply(m, near[0], RUNTIME.NumberErrbacks), RUNTIME.NumberErrbacks);
+        var m = jsnums.divide(jsnums.subtract(near[1], far[1]), jsnums.subtract(near[0], far[0]));
+        var c = jsnums.subtract(near[1], jsnums.multiply(m, near[0]));
 
         var f = function (x) {
-          return jsnums.add(jsnums.multiply(m, x, RUNTIME.NumberErrbacks), c, RUNTIME.NumberErrbacks);
+          return jsnums.add(jsnums.multiply(m, x), c);
         };
 
         var g = function (y) {
-          return jsnums.divide(jsnums.subtract(y, c, RUNTIME.NumberErrbacks), m, RUNTIME.NumberErrbacks);
+          return jsnums.divide(jsnums.subtract(y, c), m);
         };
 
         candidates = [
@@ -702,10 +702,10 @@
       }
 
       return nearest(candidates.filter(function (p) {
-        return jsnums.lessThanOrEqual(pxMin, p[0], RUNTIME.NumberErrbacks) &&
-               jsnums.lessThanOrEqual(p[0], pxMax, RUNTIME.NumberErrbacks) &&
-               jsnums.lessThanOrEqual(pyMin, p[1], RUNTIME.NumberErrbacks) &&
-               jsnums.lessThanOrEqual(p[1], pyMax, RUNTIME.NumberErrbacks);
+        return jsnums.lessThanOrEqual(pxMin, p[0]) &&
+               jsnums.lessThanOrEqual(p[0], pxMax) &&
+               jsnums.lessThanOrEqual(pyMin, p[1]) &&
+               jsnums.lessThanOrEqual(p[1], pyMax);
       }), near);
     }
 
@@ -716,8 +716,8 @@
     function toJSOptions(options) {
       return {
         color:   CLIB.libColor.convertColor(gf(options, 'color')),
-        size:    jsnums.toFixnum(gf(options, 'size'), RUNTIME.NumberErrbacks),
-        opacity: jsnums.toFixnum(gf(options, 'opacity'), RUNTIME.NumberErrbacks),
+        size:    jsnums.toFixnum(gf(options, 'size')),
+        opacity: jsnums.toFixnum(gf(options, 'opacity')),
         tip:     RUNTIME.isPyretTrue(gf(options, 'tip')),
       };
     }
@@ -913,7 +913,7 @@
 
     var sum = tab.map(function (row) { return row[1]; })
       .reduce(function (a, b) {
-        return jsnums.add(a, b, RUNTIME.NumberErrbacks);
+        return jsnums.add(a, b);
       });
     var valueScaler = libNum.scaler(0, sum, 0, 100, true);
 
@@ -1084,7 +1084,7 @@
         .scale(y)
         .orient('left')
         .tickFormat(function (d) {
-          return prettyNumToStringDigitsForAxis(yAxisDisplayScaler(jsnums.fromFixnum(d, RUNTIME.NumberErrbacks)));
+          return prettyNumToStringDigitsForAxis(yAxisDisplayScaler(jsnums.fromFixnum(d)));
         });
 
     x0.domain(data.map(function (d) { return d.label; }));
@@ -1352,7 +1352,7 @@
         .scale(y)
         .orient('left')
         .tickFormat(function (d) {
-          return prettyNumToStringDigitsForAxis(yAxisDisplayScaler(jsnums.fromFixnum(d, RUNTIME.NumberErrbacks)));
+          return prettyNumToStringDigitsForAxis(yAxisDisplayScaler(jsnums.fromFixnum(d)));
         });
 
     x0.domain(data.map(function (d) { return d.label; }));
diff --git a/src/web/js/trove/plot-lib.js b/src/web/js/trove/plot-lib.js
index 458168d3..57659e96 100644
--- a/src/web/js/trove/plot-lib.js
+++ b/src/web/js/trove/plot-lib.js
@@ -3,7 +3,6 @@
     { 'import-type': 'builtin', 'name': 'd3-lib' },
   ],
   nativeRequires: [
-    'pyret-base/js/js-numbers',
     'd3',
     'd3-tip'
   ],
@@ -17,8 +16,9 @@
       'box-chart': "tany"
     }
   },
-  theModule: function (RUNTIME, NAMESPACE, uri, CLIB, jsnums, d3, D3TIP) {
-  'use strict';
+  theModule: function (RUNTIME, NAMESPACE, uri, CLIB, d3, D3TIP) {
+    'use strict';
+    var jsnums = RUNTIME.jsnums;
   var gf = RUNTIME.getField,
       cases = RUNTIME.ffi.cases;
   var libNum =       CLIB.libNum,
@@ -69,7 +69,7 @@
     function getAxisConf(aMin, aMax) {
       const conf = {},
             scaler = libNum.scaler(aMin, aMax, 0, 1, false),
-            pos = jsnums.toFixnum(scaler(0), RUNTIME.NumberErrbacks);
+            pos = jsnums.toFixnum(scaler(0));
 
       if (0 <= pos && pos <= 1) {
         conf.bold = true;
@@ -285,7 +285,7 @@
               xMaxC.removeClass('error-bg');
               xMaxC.addClass('ok-bg');
 
-              if (jsnums.greaterThanOrEqual(xMin_val, xMax_val, RUNTIME.NumberErrbacks)) {
+              if (jsnums.greaterThanOrEqual(xMin_val, xMax_val)) {
                 xMinC.addClass('error-bg');
                 xMaxC.addClass('error-bg');
                 xMinC.removeClass('ok-bg');
@@ -313,7 +313,7 @@
                       yMaxC.removeClass('error-bg');
                       yMaxC.addClass('ok-bg');
 
-                      if (jsnums.greaterThanOrEqual(xMin_val, xMax_val, RUNTIME.NumberErrbacks)) {
+                      if (jsnums.greaterThanOrEqual(xMin_val, xMax_val)) {
                         yMinC.addClass('error-bg');
                         yMaxC.addClass('error-bg');
                         yMinC.removeClass('ok-bg');
@@ -332,7 +332,7 @@
                           numSamplesC.addClass('ok-bg');
 
                           if (RUNTIME.isPyretFalse(RUNTIME.num_is_integer(numSamples_val)) ||
-                              jsnums.lessThanOrEqual(numSamples_val, 1, RUNTIME.NumberErrbacks)) {
+                              jsnums.lessThanOrEqual(numSamples_val, 1)) {
                             numSamplesC.addClass('error-bg');
                             numSamplesC.removeClass('ok-bg');
                             return null;
@@ -372,9 +372,9 @@
       if (newWindow === null) { return; }
       var xMin_val = newWindow['x-min'];
       var xMax_val = newWindow['x-max'];
-      var move = jsnums.divide(jsnums.subtract(xMax_val, xMin_val, RUNTIME.NumberErrbacks), 10, RUNTIME.NumberErrbacks);
-      xMinC.val(prettyNumToStringDigits20(jsnums.subtract(xMin_val, move, RUNTIME.NumberErrbacks)));
-      xMaxC.val(prettyNumToStringDigits20(jsnums.subtract(xMax_val, move, RUNTIME.NumberErrbacks)));
+      var move = jsnums.divide(jsnums.subtract(xMax_val, xMin_val), 10);
+      xMinC.val(prettyNumToStringDigits20(jsnums.subtract(xMin_val, move)));
+      xMaxC.val(prettyNumToStringDigits20(jsnums.subtract(xMax_val, move)));
     }));
     controller.append($('', {
       text: '⇨',
@@ -388,8 +388,8 @@
       var xMin_val = newWindow['x-min'];
       var xMax_val = newWindow['x-max'];
       var move = jsnums.divide(jsnums.subtract(xMax_val, xMin_val), 10);
-      xMinC.val(prettyNumToStringDigits20(jsnums.add(xMin_val, move, RUNTIME.NumberErrbacks)));
-      xMaxC.val(prettyNumToStringDigits20(jsnums.add(xMax_val, move, RUNTIME.NumberErrbacks)));
+      xMinC.val(prettyNumToStringDigits20(jsnums.add(xMin_val, move)));
+      xMaxC.val(prettyNumToStringDigits20(jsnums.add(xMax_val, move)));
     }));
     controller.append($('', {
       text: '⇩',
@@ -403,8 +403,8 @@
       var yMin_val = newWindow['y-min'];
       var yMax_val = newWindow['y-max'];
       var move = jsnums.divide(jsnums.subtract(yMax_val, yMin_val), 10);
-      yMinC.val(prettyNumToStringDigits20(jsnums.subtract(yMin_val, move, RUNTIME.NumberErrbacks)));
-      yMaxC.val(prettyNumToStringDigits20(jsnums.subtract(yMax_val, move, RUNTIME.NumberErrbacks)));
+      yMinC.val(prettyNumToStringDigits20(jsnums.subtract(yMin_val, move)));
+      yMaxC.val(prettyNumToStringDigits20(jsnums.subtract(yMax_val, move)));
     }));
     controller.append($('', {
       text: '⇧',
@@ -418,8 +418,8 @@
       var yMin_val = newWindow['y-min'];
       var yMax_val = newWindow['y-max'];
       var move = jsnums.divide(jsnums.subtract(yMax_val, yMin_val), 10);
-      yMinC.val(prettyNumToStringDigits20(jsnums.add(yMin_val, move, RUNTIME.NumberErrbacks)));
-      yMaxC.val(prettyNumToStringDigits20(jsnums.add(yMax_val, move, RUNTIME.NumberErrbacks)));
+      yMinC.val(prettyNumToStringDigits20(jsnums.add(yMin_val, move)));
+      yMaxC.val(prettyNumToStringDigits20(jsnums.add(yMax_val, move)));
     }));
 
     var redraw = $('', {
@@ -469,10 +469,10 @@
         var cy = pixelToY(coord[1]);
         var radiusY = jsnums.subtract(yMax, yMin);
 
-        xMinC.val(prettyNumToStringDigits20(jsnums.subtract(cx, radiusX, RUNTIME.NumberErrbacks)));
-        xMaxC.val(prettyNumToStringDigits20(jsnums.add(cx, radiusX, RUNTIME.NumberErrbacks)));
-        yMinC.val(prettyNumToStringDigits20(jsnums.subtract(cy, radiusY, RUNTIME.NumberErrbacks)));
-        yMaxC.val(prettyNumToStringDigits20(jsnums.add(cy, radiusY, RUNTIME.NumberErrbacks)));
+        xMinC.val(prettyNumToStringDigits20(jsnums.subtract(cx, radiusX)));
+        xMaxC.val(prettyNumToStringDigits20(jsnums.add(cx, radiusX)));
+        yMinC.val(prettyNumToStringDigits20(jsnums.subtract(cy, radiusY)));
+        yMaxC.val(prettyNumToStringDigits20(jsnums.add(cy, radiusY)));
 
       })
       .on('mousedown', function () {
@@ -619,16 +619,16 @@
     var yMax = gf(windowOptions, 'y-max');
 
     function inBound(p) {
-      return jsnums.lessThanOrEqual(xMin, p[0], RUNTIME.NumberErrbacks) &&
-             jsnums.lessThanOrEqual(p[0], xMax, RUNTIME.NumberErrbacks) &&
-             jsnums.lessThanOrEqual(yMin, p[1], RUNTIME.NumberErrbacks) &&
-             jsnums.lessThanOrEqual(p[1], yMax, RUNTIME.NumberErrbacks);
+      return jsnums.lessThanOrEqual(xMin, p[0]) &&
+             jsnums.lessThanOrEqual(p[0], xMax) &&
+             jsnums.lessThanOrEqual(yMin, p[1]) &&
+             jsnums.lessThanOrEqual(p[1], yMax);
     }
 
     function dist(a, b) {
       return jsnums.add(
-        jsnums.sqr(jsnums.subtract(a[0], b[0], RUNTIME.NumberErrbacks)),
-        jsnums.sqr(jsnums.subtract(a[1], b[1], RUNTIME.NumberErrbacks)), RUNTIME.NumberErrbacks);
+        jsnums.sqr(jsnums.subtract(a[0], b[0])),
+        jsnums.sqr(jsnums.subtract(a[1], b[1])));
     }
 
     function nearest(candidates, origin) {
@@ -636,7 +636,7 @@
       var optimal = null;
       candidates.forEach(function (candidate) {
         var distance = dist(candidate, origin);
-        if (optimal === null || jsnums.lessThan(distance, optimal, RUNTIME.NumberErrbacks)) {
+        if (optimal === null || jsnums.lessThan(distance, optimal)) {
           optimal = distance;
           ans = candidate;
         }
@@ -645,7 +645,7 @@
     }
 
     function equal(a, b) {
-      return jsnums.lessThanOrEqual(a, b, RUNTIME.NumberErrbacks) && jsnums.lessThanOrEqual(b, a, RUNTIME.NumberErrbacks);
+      return jsnums.lessThanOrEqual(a, b) && jsnums.lessThanOrEqual(b, a);
     }
 
     function findPointOnEdge(near, far) {
@@ -677,15 +677,15 @@
         x = (y - c) / m         [4]   [rewrite 3]
         */
 
-        var m = jsnums.divide(jsnums.subtract(near[1], far[1], RUNTIME.NumberErrbacks), jsnums.subtract(near[0], far[0], RUNTIME.NumberErrbacks));
-        var c = jsnums.subtract(near[1], jsnums.multiply(m, near[0], RUNTIME.NumberErrbacks), RUNTIME.NumberErrbacks);
+        var m = jsnums.divide(jsnums.subtract(near[1], far[1]), jsnums.subtract(near[0], far[0]));
+        var c = jsnums.subtract(near[1], jsnums.multiply(m, near[0]));
 
         var f = function (x) {
-          return jsnums.add(jsnums.multiply(m, x, RUNTIME.NumberErrbacks), c, RUNTIME.NumberErrbacks);
+          return jsnums.add(jsnums.multiply(m, x), c);
         };
 
         var g = function (y) {
-          return jsnums.divide(jsnums.subtract(y, c, RUNTIME.NumberErrbacks), m, RUNTIME.NumberErrbacks);
+          return jsnums.divide(jsnums.subtract(y, c), m);
         };
 
         candidates = [
@@ -702,10 +702,10 @@
       }
 
       return nearest(candidates.filter(function (p) {
-        return jsnums.lessThanOrEqual(pxMin, p[0], RUNTIME.NumberErrbacks) &&
-               jsnums.lessThanOrEqual(p[0], pxMax, RUNTIME.NumberErrbacks) &&
-               jsnums.lessThanOrEqual(pyMin, p[1], RUNTIME.NumberErrbacks) &&
-               jsnums.lessThanOrEqual(p[1], pyMax, RUNTIME.NumberErrbacks);
+        return jsnums.lessThanOrEqual(pxMin, p[0]) &&
+               jsnums.lessThanOrEqual(p[0], pxMax) &&
+               jsnums.lessThanOrEqual(pyMin, p[1]) &&
+               jsnums.lessThanOrEqual(p[1], pyMax);
       }), near);
     }
 
@@ -716,8 +716,8 @@
     function toJSOptions(options) {
       return {
         color:   CLIB.libColor.convertColor(gf(options, 'color')),
-        size:    jsnums.toFixnum(gf(options, 'size'), RUNTIME.NumberErrbacks),
-        opacity: jsnums.toFixnum(gf(options, 'opacity'), RUNTIME.NumberErrbacks),
+        size:    jsnums.toFixnum(gf(options, 'size')),
+        opacity: jsnums.toFixnum(gf(options, 'opacity')),
         tip:     RUNTIME.isPyretTrue(gf(options, 'tip')),
       };
     }
@@ -913,7 +913,7 @@
 
     var sum = tab.map(function (row) { return row[1]; })
       .reduce(function (a, b) {
-        return jsnums.add(a, b, RUNTIME.NumberErrbacks);
+        return jsnums.add(a, b);
       });
     var valueScaler = libNum.scaler(0, sum, 0, 100, true);
 
@@ -1084,7 +1084,7 @@
         .scale(y)
         .orient('left')
         .tickFormat(function (d) {
-          return prettyNumToStringDigitsForAxis(yAxisDisplayScaler(jsnums.fromFixnum(d, RUNTIME.NumberErrbacks)));
+          return prettyNumToStringDigitsForAxis(yAxisDisplayScaler(jsnums.fromFixnum(d)));
         });
 
     x0.domain(data.map(function (d) { return d.label; }));
@@ -1352,7 +1352,7 @@
         .scale(y)
         .orient('left')
         .tickFormat(function (d) {
-          return prettyNumToStringDigitsForAxis(yAxisDisplayScaler(jsnums.fromFixnum(d, RUNTIME.NumberErrbacks)));
+          return prettyNumToStringDigitsForAxis(yAxisDisplayScaler(jsnums.fromFixnum(d)));
         });
 
     x0.domain(data.map(function (d) { return d.label; }));
diff --git a/src/web/js/trove/world.js b/src/web/js/trove/world.js
index 3909b94a..22186cec 100644
--- a/src/web/js/trove/world.js
+++ b/src/web/js/trove/world.js
@@ -5,7 +5,7 @@
     { "import-type": "builtin", "name": "valueskeleton" },
     { "import-type": "builtin", "name": "reactors" }
   ],
-  nativeRequires: ["pyret-base/js/js-numbers"],
+  nativeRequires: [],
   provides: {
     shorthands: {
       "WCOofA": ["tyapp", ["local", "WorldConfigOption"], [["tid", "a"]]],
@@ -52,7 +52,8 @@
       "WorldConfigOption": ["data", "WorldConfigOption", ["a"], [], {}]
     }
   },
-  theModule: function(runtime, namespace, uri, imageLibraryLib, rawJsworld, VSlib, reactors, jsnums) {
+  theModule: function(runtime, namespace, uri, imageLibraryLib, rawJsworld, VSlib, reactors) {
+    var jsnums = runtime.jsnums;
     var imageLibrary = runtime.getField(imageLibraryLib, "internal");
     var isImage = imageLibrary.isImage;
     var VS = runtime.getField(VSlib, "values");