Repository: bokeh/bokeh

Issue:
Rewrite bokehjs in TypeScript
This is a meta issue for moving bokehjs from coffeescript to typescript.

Module status:
- [x] api
- [x] core
  - [x] layout
  - [x] util
- [x] models
  - [x] annotations
  - [x] axes
  - [x] callbacks
  - [x] canvas
  - [x] expressions
  - [x] filters
  - [x] formatters
  - [x] glyphs
    - [x] webgl
  - [x] graphs
  - [x] grids
  - [x] layouts
  - [x] mappers
  - [x] markers
  - [x] plots
  - [x] ranges
  - [x] renderers
  - [x] scales
  - [x] sources
  - [x] tickers
  - [x] tiles
  - [x] tools
    - [x] toolbars
  - [x] transforms
  - [x] widgets
    - [x] tables
- [x] client
- [x] protocol
- [x] document
- [x] embed


Discussion:
btw. If anyone else would like to join in, then make sure to commit all changes in two stages. First commit rename from `path/file.coffee` to `path/file.ts` and then commit changes necessary to make that file compile. This helps git to maintain history of renamed files.
@mattpap just FYI there are some outside folks potentially interested in helping parallelize this effort after the low level core classes are done, so just request to keep this issue updated with progress as things go. 
Asking this because I'm curious, what is the motivation for switching from CoffeeScript to TypeScript?
> what is the motivation for switching from CoffeeScript to TypeScript?

The main reason is static typing of bokehjs to reduce maintenance burden and straighten the APIs. I'm not even half through the rewrite, and I already fixed a few dozen of bugs and API inconsistencies. Another reason is that CoffeeScript is a bad language. It's nice on the surface and often eye pleasing, but its certain features are straight from a nightmare, e.g. scoping rules, grammar, implicit returns (to name a few). A nice example of this is issue #6588. TypeScript isn't perfect either, but we don't have much choice, and still this transition is a big improvement of the current state of the art. Additionally, at the time of making this decision, CoffeeScript was essentially a dead language. That changed recently with CoffeeScript 2, which isn't a big improvement, but at least allowed us to speed up the transition. There are other smaller yet important reasons (e.g. tooling).

Resolving patch:
diff --git a/bokeh/models/annotations.py b/bokeh/models/annotations.py
--- a/bokeh/models/annotations.py
+++ b/bokeh/models/annotations.py
@@ -23,7 +23,7 @@
 from .mappers import ContinuousColorMapper
 from .renderers import GlyphRenderer, Renderer
 from .sources import ColumnDataSource, DataSource
-from .tickers import BasicTicker, Ticker
+from .tickers import BasicTicker, ContinuousTicker
 
 @abstract
 class Annotation(Renderer):
@@ -43,6 +43,23 @@ class TextAnnotation(Annotation):
 
     '''
 
+    render_mode = Enum(RenderMode, default="canvas", help="""
+    Specifies whether the text is rendered as a canvas element or as an
+    css element overlaid on the canvas. The default mode is "canvas".
+
+    .. note::
+        The CSS labels won't be present in the output using the "save" tool.
+
+    .. warning::
+        Not all visual styling properties are supported if the render_mode is
+        set to "css". The border_line_dash property isn't fully supported and
+        border_line_dash_offset isn't supported at all. Setting text_alpha will
+        modify the opacity of the entire background box and border in addition
+        to the text. Finally, clipping Label annotations inside of the plot
+        area isn't supported in "css" mode.
+
+    """)
+
 class LegendItem(Model):
     '''
 
@@ -244,7 +261,7 @@ class ColorBar(Annotation):
     The distance (in pixels) to separate the title from the color bar.
     """)
 
-    ticker = Instance(Ticker, default=lambda: BasicTicker(), help="""
+    ticker = Instance(ContinuousTicker, default=lambda: BasicTicker(), help="""
     A Ticker to use for computing locations of axis components.
     """)
 
@@ -647,23 +664,6 @@ class Label(TextAnnotation):
     rendering an annotation on the plot. If unset, use the default y-range.
     """)
 
-    render_mode = Enum(RenderMode, default="canvas", help="""
-    Specifies whether the text is rendered as a canvas element or as an
-    css element overlaid on the canvas. The default mode is "canvas".
-
-    .. note::
-        The CSS labels won't be present in the output using the "save" tool.
-
-    .. warning::
-        Not all visual styling properties are supported if the render_mode is
-        set to "css". The border_line_dash property isn't fully supported and
-        border_line_dash_offset isn't supported at all. Setting text_alpha will
-        modify the opacity of the entire background box and border in addition
-        to the text. Finally, clipping Label annotations inside of the plot
-        area isn't supported in "css" mode.
-
-    """)
-
 class LabelSet(TextAnnotation):
     ''' Render multiple text labels as annotations.
 
@@ -765,23 +765,6 @@ class LabelSet(TextAnnotation):
     rendering annotations on the plot. If unset, use the default y-range.
     """)
 
-    render_mode = Enum(RenderMode, default="canvas", help="""
-    Specifies whether the text is rendered as a canvas element or as an
-    css element overlaid on the canvas. The default mode is "canvas".
-
-    .. note::
-        The CSS labels won't be present in the output using the "save" tool.
-
-    .. warning::
-        Not all visual styling properties are supported if the render_mode is
-        set to "css". The border_line_dash property isn't fully supported and
-        border_line_dash_offset isn't supported at all. Setting text_alpha will
-        modify the opacity of the entire background box and border in addition
-        to the text. Finally, clipping Label annotations inside of the plot
-        area isn't supported in "css" mode.
-
-    """)
-
 class PolyAnnotation(Annotation):
     ''' Render a shaded polygonal region as an annotation.
 
@@ -954,23 +937,6 @@ class Title(TextAnnotation):
 
     border_line_color = Override(default=None)
 
-    render_mode = Enum(RenderMode, default="canvas", help="""
-    Specifies whether the text is rendered as a canvas element or as an
-    css element overlaid on the canvas. The default mode is "canvas".
-
-    .. note::
-        The CSS labels won't be present in the output using the "save" tool.
-
-    .. warning::
-        Not all visual styling properties are supported if the render_mode is
-        set to "css". The border_line_dash property isn't fully supported and
-        border_line_dash_offset isn't supported at all. Setting text_alpha will
-        modify the opacity of the entire background box and border in addition
-        to the text. Finally, clipping Label annotations inside of the plot
-        area isn't supported in "css" mode.
-
-    """)
-
 class Tooltip(Annotation):
     ''' Render a tooltip.
 


Test patch:
diff --git a/bokehjs/test/models/annotations/legend_item.coffee b/bokehjs/test/models/annotations/legend_item.coffee
--- a/bokehjs/test/models/annotations/legend_item.coffee
+++ b/bokehjs/test/models/annotations/legend_item.coffee
@@ -90,12 +90,12 @@ describe "LegendItem", ->
     it "should return undefined if label property is null", ->
       legend_item = new LegendItem({label: null})
       field = legend_item.get_field_from_label_prop()
-      expect(field).to.be.undefined
+      expect(field).to.be.null
 
     it "should return undefined if label property is value", ->
       legend_item = new LegendItem({label: {value: 'milk'}})
       field = legend_item.get_field_from_label_prop()
-      expect(field).to.be.undefined
+      expect(field).to.be.null
 
     it "should return field if label property is field", ->
       legend_item = new LegendItem({label: {field: 'milk'}})
diff --git a/bokehjs/test/models/mappers/categorical_color_mapper.coffee b/bokehjs/test/models/mappers/categorical_color_mapper.coffee
--- a/bokehjs/test/models/mappers/categorical_color_mapper.coffee
+++ b/bokehjs/test/models/mappers/categorical_color_mapper.coffee
@@ -5,7 +5,7 @@ utils = require "../../utils"
 
 describe "CategoricalColorMapper module", ->
 
-  describe "CategoricalColorMapper._get_values method", ->
+  describe "CategoricalColorMapper.v_compute method", ->
 
     describe "with 1-level data factors", ->
 
@@ -15,7 +15,7 @@ describe "CategoricalColorMapper module", ->
           palette: palette
           factors: ["a", "b", "c"]
         })
-        vals = cm._get_values(["c", "b", "a", "b"], palette)
+        vals = cm.v_compute(["c", "b", "a", "b"])
         expect(vals).to.be.deep.equal(["blue", "green", "red", "green"])
 
       it "should map data unknown data to nan_color value", ->
@@ -25,7 +25,7 @@ describe "CategoricalColorMapper module", ->
           nan_color: "gray"
           factors: ["a", "b", "c"]
         })
-        vals = cm._get_values(["d", "a", "b"], palette)
+        vals = cm.v_compute(["d", "a", "b"])
         expect(vals).to.be.deep.equal(["gray", "red", "green"])
 
       it "should map data with short palette to nan_color value", ->
@@ -35,7 +35,7 @@ describe "CategoricalColorMapper module", ->
           nan_color: "gray"
           factors: ["a", "b", "c"]
         })
-        vals = cm._get_values(["a", "b", "c"], palette)
+        vals = cm.v_compute(["a", "b", "c"])
         expect(vals).to.be.deep.equal(["red", "green", "gray"])
 
       it "should disregard any start or end values", ->
@@ -46,17 +46,17 @@ describe "CategoricalColorMapper module", ->
         })
 
         cm.start = 1
-        vals = cm._get_values(["c", "b", "a", "b"], palette)
+        vals = cm.v_compute(["c", "b", "a", "b"])
         expect(vals).to.be.deep.equal(["blue", "green", "red", "green"])
 
         cm.start = null
         cm.end = 2
-        vals = cm._get_values(["c", "b", "a", "b"], palette)
+        vals = cm.v_compute(["c", "b", "a", "b"])
         expect(vals).to.be.deep.equal(["blue", "green", "red", "green"])
 
         cm.start = 1
         cm.end = 2
-        vals = cm._get_values(["c", "b", "a", "b"], palette)
+        vals = cm.v_compute(["c", "b", "a", "b"])
         expect(vals).to.be.deep.equal(["blue", "green", "red", "green"])
 
   describe "with 2-level data factors", ->
@@ -71,7 +71,7 @@ describe "CategoricalColorMapper module", ->
           factors: (x.slice(0,1)[0] for x in factors)
           end: 1
         })
-        vals = cm._get_values(factors, palette)
+        vals = cm.v_compute(factors)
         expect(vals).to.be.deep.equal(palette)
 
       it "should map factors to palette with start=1, end=2", ->
@@ -83,7 +83,7 @@ describe "CategoricalColorMapper module", ->
           start: 1
           end: 2
         })
-        vals = cm._get_values(factors, palette)
+        vals = cm.v_compute(factors)
         expect(vals).to.be.deep.equal(palette)
 
       for i in [0..1]
@@ -104,7 +104,7 @@ describe "CategoricalColorMapper module", ->
               end: j
             })
 
-            vals = cm._get_values([["a", "1"]], palette)
+            vals = cm.v_compute([["a", "1"]])
             expect(vals).to.be.deep.equal(["gray"])
 
             cm = new CategoricalColorMapper({
@@ -114,7 +114,7 @@ describe "CategoricalColorMapper module", ->
               end: j
             })
 
-            vals = cm._get_values([["a", "1"]], palette)
+            vals = cm.v_compute([["a", "1"]])
             expect(vals).to.be.deep.equal(["gray"])
 
     describe "and 2-level palette factors", ->
@@ -126,7 +126,7 @@ describe "CategoricalColorMapper module", ->
           palette: palette
           factors: factors
         })
-        vals = cm._get_values(factors, palette)
+        vals = cm.v_compute(factors)
         expect(vals).to.be.deep.equal(palette)
 
       it "should map factors to palette with start=0, end=2", ->
@@ -138,7 +138,7 @@ describe "CategoricalColorMapper module", ->
           start: 0
           end: 2
         })
-        vals = cm._get_values(factors, palette)
+        vals = cm.v_compute(factors)
         expect(vals).to.be.deep.equal(palette)
 
       for i in [0..1]
@@ -159,7 +159,7 @@ describe "CategoricalColorMapper module", ->
               end: j
             })
 
-            vals = cm._get_values([["a", "1"]], palette)
+            vals = cm.v_compute([["a", "1"]])
             expect(vals).to.be.deep.equal(["gray"])
 
   describe "with 3-level data factors", ->
@@ -174,7 +174,7 @@ describe "CategoricalColorMapper module", ->
           factors: (x.slice(0,1)[0] for x in factors)
           end: 1
         })
-        vals = cm._get_values(factors, palette)
+        vals = cm.v_compute(factors)
         expect(vals).to.be.deep.equal(palette)
 
       it "should map factors to palette with start=1, end=2", ->
@@ -186,7 +186,7 @@ describe "CategoricalColorMapper module", ->
           start: 1
           end: 2
         })
-        vals = cm._get_values(factors, palette)
+        vals = cm.v_compute(factors)
         expect(vals).to.be.deep.equal(palette)
 
       it "should map factors to palette with start=2, end=3", ->
@@ -198,7 +198,7 @@ describe "CategoricalColorMapper module", ->
           start: 2
           end: 3
         })
-        vals = cm._get_values(factors, palette)
+        vals = cm.v_compute(factors)
         expect(vals).to.be.deep.equal(palette)
 
       for i in [0..2]
@@ -219,10 +219,10 @@ describe "CategoricalColorMapper module", ->
               end: j
             })
 
-            vals = cm._get_values([["a", "1", "foo"]], palette)
+            vals = cm.v_compute([["a", "1", "foo"]])
             expect(vals).to.be.deep.equal(["gray"])
 
-            vals = cm._get_values([["a", "1", "baz"]], palette)
+            vals = cm.v_compute([["a", "1", "baz"]])
             expect(vals).to.be.deep.equal(["gray"])
 
             cm = new CategoricalColorMapper({
@@ -232,10 +232,10 @@ describe "CategoricalColorMapper module", ->
               end: j
             })
 
-            vals = cm._get_values([["a", "1", "foo"]], palette)
+            vals = cm.v_compute([["a", "1", "foo"]])
             expect(vals).to.be.deep.equal(["gray"])
 
-            vals = cm._get_values([["a", "1", "baz"]], palette)
+            vals = cm.v_compute([["a", "1", "baz"]])
             expect(vals).to.be.deep.equal(["gray"])
 
             cm = new CategoricalColorMapper({
@@ -245,10 +245,10 @@ describe "CategoricalColorMapper module", ->
               end: j
             })
 
-            vals = cm._get_values([["a", "1", "foo"]], palette)
+            vals = cm.v_compute([["a", "1", "foo"]])
             expect(vals).to.be.deep.equal(["gray"])
 
-            vals = cm._get_values([["a", "1", "baz"]], palette)
+            vals = cm.v_compute([["a", "1", "baz"]])
             expect(vals).to.be.deep.equal(["gray"])
 
     describe "and 2-level palette factors", ->
@@ -261,7 +261,7 @@ describe "CategoricalColorMapper module", ->
           factors: (x.slice(0,2) for x in factors)
           end: 2
         })
-        vals = cm._get_values(factors, palette)
+        vals = cm.v_compute(factors)
         expect(vals).to.be.deep.equal(palette)
 
       it "should map factors to palette with start=1, end=3", ->
@@ -274,7 +274,7 @@ describe "CategoricalColorMapper module", ->
           end: 3
         })
 
-        vals = cm._get_values(factors, palette)
+        vals = cm.v_compute(factors)
         expect(vals).to.be.deep.equal(palette)
 
       for i in [0..2]
@@ -295,16 +295,16 @@ describe "CategoricalColorMapper module", ->
               end: j
             })
 
-            vals = cm._get_values(["a"], palette)
+            vals = cm.v_compute(["a"])
             expect(vals).to.be.deep.equal(["gray"])
 
-            vals = cm._get_values([["a", "1"]], palette)
+            vals = cm.v_compute([["a", "1"]])
             expect(vals).to.be.deep.equal(["gray"])
 
-            vals = cm._get_values([["a", "1", "foo"]], palette)
+            vals = cm.v_compute([["a", "1", "foo"]])
             expect(vals).to.be.deep.equal(["gray"])
 
-            vals = cm._get_values([["a", "1", "baz"]], palette)
+            vals = cm.v_compute([["a", "1", "baz"]])
             expect(vals).to.be.deep.equal(["gray"])
 
             cm = new CategoricalColorMapper({
@@ -314,16 +314,16 @@ describe "CategoricalColorMapper module", ->
               end: j
             })
 
-            vals = cm._get_values(["a"], palette)
+            vals = cm.v_compute(["a"])
             expect(vals).to.be.deep.equal(["gray"])
 
-            vals = cm._get_values([["a", "1"]], palette)
+            vals = cm.v_compute([["a", "1"]])
             expect(vals).to.be.deep.equal(["gray"])
 
-            vals = cm._get_values([["a", "1", "foo"]], palette)
+            vals = cm.v_compute([["a", "1", "foo"]])
             expect(vals).to.be.deep.equal(["gray"])
 
-            vals = cm._get_values([["a", "1", "baz"]], palette)
+            vals = cm.v_compute([["a", "1", "baz"]])
             expect(vals).to.be.deep.equal(["gray"])
 
     describe "and 3-level palette factors", ->
@@ -335,7 +335,7 @@ describe "CategoricalColorMapper module", ->
           palette: palette
           factors: factors
         })
-        vals = cm._get_values(factors, palette)
+        vals = cm.v_compute(factors)
         expect(vals).to.be.deep.equal(palette)
 
       it "should map factors to palette with start=0, end=3", ->
@@ -347,7 +347,7 @@ describe "CategoricalColorMapper module", ->
           start: 0
           end: 3
         })
-        vals = cm._get_values(factors, palette)
+        vals = cm.v_compute(factors)
         expect(vals).to.be.deep.equal(palette)
 
       for i in [0..2]
@@ -368,14 +368,14 @@ describe "CategoricalColorMapper module", ->
             cm.start = i
             cm.end = j
 
-            vals = cm._get_values(["a"], palette)
+            vals = cm.v_compute(["a"])
             expect(vals).to.be.deep.equal(["gray"])
 
-            vals = cm._get_values([["a", "1"]], palette)
+            vals = cm.v_compute([["a", "1"]])
             expect(vals).to.be.deep.equal(["gray"])
 
-            vals = cm._get_values([["a", "1", "foo"]], palette)
+            vals = cm.v_compute([["a", "1", "foo"]])
             expect(vals).to.be.deep.equal(["gray"])
 
-            vals = cm._get_values([["a", "1", "baz"]], palette)
+            vals = cm.v_compute([["a", "1", "baz"]])
             expect(vals).to.be.deep.equal(["gray"])
diff --git a/bokehjs/test/models/mappers/color_mapper.coffee b/bokehjs/test/models/mappers/color_mapper.coffee
--- a/bokehjs/test/models/mappers/color_mapper.coffee
+++ b/bokehjs/test/models/mappers/color_mapper.coffee
@@ -2,66 +2,17 @@
 sinon = require "sinon"
 utils = require "../../utils"
 
-{ColorMapper} = utils.require("models/mappers/color_mapper")
+{_convert_color, _convert_palette} = utils.require("models/mappers/color_mapper")
 
 describe "ColorMapper module", ->
 
-  beforeEach ->
-    @color_mapper = new ColorMapper({palette: [0x31a354, 0xaddd8e, 0xf7fcb9]})
+  it "support _convert_color() function", ->
+    expect(_convert_color("cadetblue")).to.be.equal(0x5f9ea0ff)
+    expect(_convert_color("rgb(95,158,160)")).to.be.equal(0x5f9ea0ff)
+    expect(_convert_color("#5f9ea0")).to.be.equal(0x5f9ea0ff)
+    expect(_convert_color("#5F9EA0")).to.be.equal(0x5f9ea0ff)
 
-  describe "ColorMapper.initializer method", ->
-
-    it "Should set `_little_endian` private attribute", ->
-      # is_little_endian is platform (browser?) dependent, so we're just checking it's set
-      expect(@color_mapper).to.have.property("_little_endian")
-
-    it "Should set `_palette` private attribute", ->
-      # This method is explicitly tested next, we're just checking it's set here
-      expect(@color_mapper).to.have.property("_palette")
-
-  describe "ColorMapper._build_palette method", ->
-
-    it "should convert palette to Uint32Array", ->
-      expected = { '0': 3253076, '1': 11394446, '2': 16252089 }
-      expect(@color_mapper._build_palette([0x31a354, 0xaddd8e, 0xf7fcb9])).to.be.deep.equal(expected)
-
-  describe "Changing palette model attr should reset _build_palette private attr", ->
-
-    it "Should call `_build_palette` method and change `_palette` attr value", ->
-      spy = sinon.spy(ColorMapper.prototype, "_build_palette")
-
-      new_palette = [0x43a2ca, 0xa8ddb5, 0xe0f3db]
-      @color_mapper.palette = new_palette
-
-      expect(spy.withArgs(new_palette).calledOnce).to.be.true
-      expect(@color_mapper._palette).to.be.deep.equal({ '0': 4432586, '1': 11066805, '2': 14742491 })
-
-      spy.restore()
-
-  ### XXX: ColorMapper is an abstract class, so _get_values() isn't defined yet.
-  describe "ColorMapper.v_map_screen method", ->
-    it "should call get_values with data and palette", ->
-      spy = sinon.spy(ColorMapper.prototype, "_get_values")
-      palette =  ["blue", "red", "green", "pink", "black"]
-      data = [1, 2, 3, 4, 5]
-      @color_mapper._palette = palette
-      @color_mapper.v_map_screen(data)
-      expect(spy.withArgs(data, palette).calledOnce).to.be.true
-      spy.restore()
-
-  describe "ColorMapper.compute method", ->
-    it "should return null", ->
-      # single value transform does not make sense for color mapper
-      val = @color_mapper.compute(1)
-      expect(val).to.be.null
-
-  describe "ColorMapper.v_compute method", ->
-    it "should call get_values with palette", ->
-      spy = sinon.spy(ColorMapper.prototype, "_get_values")
-      palette =  ["blue", "red", "green", "pink", "black"]
-      data = [1, 2, 3, 4, 5]
-      @color_mapper.palette = palette
-      @color_mapper.v_compute(data)
-      expect(spy.withArgs(data, palette).calledOnce).to.be.true
-      spy.restore()
-  ###
+  it "support _convert_palette() function", ->
+    palette = ["red", "green", "blue", "#31a354", "#addd8e", "#F7FCB9"]
+    expected = Uint32Array.of(0xff0000ff, 0x008000ff, 0x0000ffff, 0x31a354ff, 0xaddd8eff, 0xf7fcb9ff)
+    expect(_convert_palette(palette)).to.be.deep.equal(expected)
diff --git a/bokehjs/test/models/mappers/linear_color_mapper.coffee b/bokehjs/test/models/mappers/linear_color_mapper.coffee
--- a/bokehjs/test/models/mappers/linear_color_mapper.coffee
+++ b/bokehjs/test/models/mappers/linear_color_mapper.coffee
@@ -5,29 +5,7 @@ utils = require "../../utils"
 
 describe "LinearColorMapper module", ->
 
-  describe "LinearColorMapper initialization", ->
-
-    it "Should set _nan_color, _low_color, _high_color attributes as ints", ->
-
-      color_mapper = new LinearColorMapper({
-        palette: ["red", "green", "blue"]
-        nan_color: "cadetblue"
-        low_color: "rgb(95,158,160)"
-        high_color: "#5F9EA0"
-        })
-
-      expect(color_mapper._nan_color).to.be.equal(1604231423)
-      expect(color_mapper._low_color).to.be.equal(1604231423)
-      expect(color_mapper._high_color).to.be.equal(1604231423)
-
-    it "If unset _low_color, _high_color should be undefined", ->
-      color_mapper = new LinearColorMapper({
-        palette: ["red", "green", "blue"]
-        })
-      expect(color_mapper._low_color).to.be.undefined
-      expect(color_mapper._high_color).to.be.undefined
-
-  describe "LinearColorMapper._get_values method", ->
+  describe "LinearColorMapper.v_compute method", ->
 
     it "Should map values along linear scale with high/low unset", ->
       palette = ["red", "green", "blue"]
@@ -35,28 +13,28 @@ describe "LinearColorMapper module", ->
           palette: palette
         })
 
-      vals = color_mapper._get_values([99.999, 67, 50, 32, 0.0001], palette)
+      vals = color_mapper.v_compute([99.999, 67, 50, 32, 0.0001])
       expect(vals).to.be.deep.equal(["blue", "blue", "green", "red", "red"])
 
-      vals = color_mapper._get_values([0.0001, 32, 50, 67, 99.999], palette)
+      vals = color_mapper.v_compute([0.0001, 32, 50, 67, 99.999])
       expect(vals).to.be.deep.equal(["red", "red", "green", "blue", "blue"])
 
-      vals = color_mapper._get_values([1, 2, 3], palette)
+      vals = color_mapper.v_compute([1, 2, 3])
       expect(vals).to.be.deep.equal(["red", "green", "blue"])
 
-      vals = color_mapper._get_values([3, 2, 1], palette)
+      vals = color_mapper.v_compute([3, 2, 1])
       expect(vals).to.be.deep.equal(["blue", "green", "red"])
 
-      vals = color_mapper._get_values([0, 1, 2], palette)
+      vals = color_mapper.v_compute([0, 1, 2])
       expect(vals).to.be.deep.equal(["red", "green", "blue"])
 
-      vals = color_mapper._get_values([2, 1, 0], palette)
+      vals = color_mapper.v_compute([2, 1, 0])
       expect(vals).to.be.deep.equal(["blue", "green", "red"])
 
-      vals = color_mapper._get_values([-1, 0, 1], palette)
+      vals = color_mapper.v_compute([-1, 0, 1])
       expect(vals).to.be.deep.equal(["red", "green", "blue"])
 
-      vals = color_mapper._get_values([1, 0, -1], palette)
+      vals = color_mapper.v_compute([1, 0, -1])
       expect(vals).to.be.deep.equal(["blue", "green", "red"])
 
     it "Should map values along linear scale with high/low set", ->
@@ -67,7 +45,7 @@ describe "LinearColorMapper module", ->
           palette: palette
         })
 
-      vals = color_mapper._get_values([1, 2, 3], palette)
+      vals = color_mapper.v_compute([1, 2, 3])
       expect(vals).to.be.deep.equal(["red", "green", "blue"])
 
     it "Should map values along linear scale with high/low set in other direction", ->
@@ -78,7 +56,7 @@ describe "LinearColorMapper module", ->
           palette: palette
         })
 
-      vals = color_mapper._get_values([1, 2, 3], palette)
+      vals = color_mapper.v_compute([1, 2, 3])
       expect(vals).to.be.deep.equal(["blue", "green", "red"])
 
     it "Should map data below low value to low", ->
@@ -89,7 +67,7 @@ describe "LinearColorMapper module", ->
           palette: palette
         })
 
-      vals = color_mapper._get_values([0, 1, 2], palette)
+      vals = color_mapper.v_compute([0, 1, 2])
       expect(vals).to.be.deep.equal(["red", "red", "green"])
 
     it "Should map data above high value to high", ->
@@ -100,7 +78,7 @@ describe "LinearColorMapper module", ->
           palette: palette
         })
 
-      vals = color_mapper._get_values([2, 3, 4], palette)
+      vals = color_mapper.v_compute([2, 3, 4])
       expect(vals).to.be.deep.equal(["green", "blue", "blue"])
 
     it "Should map data NaN to nan_color value", ->
@@ -112,7 +90,7 @@ describe "LinearColorMapper module", ->
           nan_color: "gray"
         })
 
-      vals = color_mapper._get_values([1, NaN, 3], palette)
+      vals = color_mapper.v_compute([1, NaN, 3])
       expect(vals).to.be.deep.equal(["red", "gray", "blue"])
 
     it "Should map data NaN to nan_color value when high/low not set", ->
@@ -122,7 +100,7 @@ describe "LinearColorMapper module", ->
           nan_color: "gray"
         })
 
-      vals = color_mapper._get_values([1, NaN, 3], palette)
+      vals = color_mapper.v_compute([1, NaN, 3])
       expect(vals).to.be.deep.equal(["red", "gray", "blue"])
 
     it "Should map high/low values to high_color/low_color, if provided", ->
@@ -135,18 +113,5 @@ describe "LinearColorMapper module", ->
           high_color: "orange"
         })
 
-      vals = color_mapper._get_values([-1, 0, 1, 2, 3], palette)
+      vals = color_mapper.v_compute([-1, 0, 1, 2, 3])
       expect(vals).to.be.deep.equal(["pink", "red", "green", "blue", "orange"])
-
-    it "Should map high/low values to _high_color/_low_color, if image_glyph=true", ->
-      palette = [1, 2, 3]
-      color_mapper = new LinearColorMapper({
-          low: 0
-          high: 2
-          palette: palette
-          low_color: "pink" # converts to 4290825215
-          high_color: "orange" # converts to 4289003775
-        })
-
-      vals = color_mapper._get_values([-1, 0, 1, 2, 3], palette, true)
-      expect(vals).to.be.deep.equal([4290825215, 1, 2, 3, 4289003775])
diff --git a/bokehjs/test/models/mappers/log_color_mapper.coffee b/bokehjs/test/models/mappers/log_color_mapper.coffee
--- a/bokehjs/test/models/mappers/log_color_mapper.coffee
+++ b/bokehjs/test/models/mappers/log_color_mapper.coffee
@@ -5,29 +5,7 @@ utils = require "../../utils"
 
 describe "LogColorMapper module", ->
 
-  describe "LogColorMapper initialization", ->
-
-    it "Should set _nan_color, _low_color, _high_color attributes as ints", ->
-
-      color_mapper = new LogColorMapper({
-        palette: ["red", "green", "blue"]
-        nan_color: "cadetblue"
-        low_color: "rgb(95,158,160)"
-        high_color: "#5F9EA0"
-        })
-
-      expect(color_mapper._nan_color).to.be.equal(1604231423)
-      expect(color_mapper._low_color).to.be.equal(1604231423)
-      expect(color_mapper._high_color).to.be.equal(1604231423)
-
-    it "If unset _low_color, _high_color should be undefined", ->
-      color_mapper = new LogColorMapper({
-        palette: ["red", "green", "blue"]
-        })
-      expect(color_mapper._low_color).to.be.undefined
-      expect(color_mapper._high_color).to.be.undefined
-
-  describe "LogColorMapper.v_map_screen method", ->
+  describe "LogColorMapper.rgba_mapper.v_compute() method", ->
 
     it "Should correctly map values along log scale", ->
       color_mapper = new LogColorMapper({
@@ -36,10 +14,10 @@ describe "LogColorMapper module", ->
           palette: ["#3288bd", "#abdda4", "#fee08b"]
         })
 
-      buf8 = new Uint8ClampedArray(color_mapper.v_map_screen([2]))
+      buf8 = color_mapper.rgba_mapper.v_compute([2])
       expect([buf8[0], buf8[1], buf8[2], buf8[3]]).to.be.deep.equal [50, 136, 189, 255]
 
-      buf8 = new Uint8ClampedArray(color_mapper.v_map_screen([20]))
+      buf8 = color_mapper.rgba_mapper.v_compute([20])
       expect([buf8[0], buf8[1], buf8[2], buf8[3]]).to.be.deep.equal [254, 224, 139, 255]
 
     it "Should correctly handle zero values", ->
@@ -49,10 +27,10 @@ describe "LogColorMapper module", ->
           palette: ["#3288bd", "#abdda4", "#fee08b"]
         })
 
-      buf8 = new Uint8ClampedArray(color_mapper.v_map_screen([0]))
+      buf8 = color_mapper.rgba_mapper.v_compute([0])
       expect([buf8[0], buf8[1], buf8[2], buf8[3]]).to.be.deep.equal [50, 136, 189, 255]
 
-  describe "LogColorMapper._get_values method", ->
+  describe "LogColorMapper.v_compute method", ->
 
     it "Should map data below low value to low", ->
       palette = ["red", "green", "blue"]
@@ -62,7 +40,7 @@ describe "LogColorMapper module", ->
           palette: palette
         })
 
-      vals = color_mapper._get_values([0, 1, 10], palette)
+      vals = color_mapper.v_compute([0, 1, 10])
       expect(vals).to.be.deep.equal(["red", "red", "green"])
 
     it "Should map data above high value to high", ->
@@ -73,7 +51,7 @@ describe "LogColorMapper module", ->
           palette: palette
         })
 
-      vals = color_mapper._get_values([10, 100, 101], palette)
+      vals = color_mapper.v_compute([10, 100, 101])
       expect(vals).to.be.deep.equal(["green", "blue", "blue"])
 
     it "Should map data NaN to nan_color value", ->
@@ -85,7 +63,7 @@ describe "LogColorMapper module", ->
           nan_color: "gray"
         })
 
-      vals = color_mapper._get_values([1, NaN, 100], palette)
+      vals = color_mapper.v_compute([1, NaN, 100])
       expect(vals).to.be.deep.equal(["red", "gray", "blue"])
 
     it "Should map data NaN to nan_color value when high/low not set", ->
@@ -95,7 +73,7 @@ describe "LogColorMapper module", ->
           nan_color: "gray"
         })
 
-      vals = color_mapper._get_values([1, NaN, 100], palette)
+      vals = color_mapper.v_compute([1, NaN, 100])
       expect(vals).to.be.deep.equal(["red", "gray", "blue"])
 
     it "Should map high/low values to high_color/low_color, if provided", ->
@@ -108,18 +86,5 @@ describe "LogColorMapper module", ->
           palette: palette
         })
 
-      vals = color_mapper._get_values([0.5, 1, 10, 100, 101], palette)
+      vals = color_mapper.v_compute([0.5, 1, 10, 100, 101])
       expect(vals).to.be.deep.equal(["pink", "red", "green", "blue", "orange"])
-
-    it "Should map high/low values to _high_color/_low_color, if image_glyph=true", ->
-      palette = [1, 2, 3]
-      color_mapper = new LogColorMapper({
-          low: 1
-          high: 100
-          palette: palette
-          low_color: "pink" # converts to 4290825215
-          high_color: "orange" # converts to 4289003775
-        })
-
-      vals = color_mapper._get_values([-1, 1, 10, 100, 101], palette, true)
-      expect(vals).to.be.deep.equal([4290825215, 1, 2, 3, 4289003775])