function makeOffscreenTabTestDocument(script) {
  return '\
<html><body style="background-color:black; margin:0; padding:0;"></body>\n\
<script>\n\
var redColor = [255, 0, 0];\n\
var greenColor = [0, 255, 0];\n\
var blueColor = [0, 0, 255];\n\
\n\
var fillColor = [0, 0, 0];\n\
function setFillColor(color) {\n\
  fillColor = color;\n\
}\n\
\n\
var debugMessage = "";\n\
function setDebugMessage(msg) {\n\
  debugMessage = msg;\n\
}\n\
\n\
function updateTestPattern() {\n\
  if (!this.canvas) {\n\
    this.canvas = document.createElement("canvas");\n\
    this.canvas.width = ' + width + ';\n\
    this.canvas.height = ' + height + ';\n\
    this.canvas.style.position = "absolute";\n\
    this.canvas.style.top = "0px";\n\
    this.canvas.style.left = "0px";\n\
    this.canvas.style.width = "100%";\n\
    this.canvas.style.height = "100%";\n\
    document.body.appendChild(this.canvas);\n\
  }\n\
  var context = this.canvas.getContext("2d");\n\
  // Fill with solid color.\n\
  context.fillStyle = "rgb(" + fillColor + ")";\n\
  context.fillRect(0, 0, this.canvas.width, this.canvas.height);\n\
  // Draw the circle that moves around the page.\n\
  var inverseColor =\n\
      [255 - fillColor[0], 255 - fillColor[1], 255 - fillColor[2]];\n\
  if (debugMessage) {\n\
    context.fillStyle = "rgb(" + inverseColor + ")";\n\
    context.font = "xx-small monospace";\n\
    context.fillText(debugMessage, 0, 0);\n\
  }\n\
  context.fillStyle = "rgba(" + inverseColor + ", 0.5)";\n\
  context.beginPath();\n\
  if (!this.frameNumber) {\n\
    this.frameNumber = 1;\n\
  } else {\n\
    ++this.frameNumber;\n\
  }\n\
  var i = this.frameNumber % 200;\n\
  var t = (this.frameNumber + 3000) * (0.01 + i / 8000.0);\n\
  var x = (Math.sin(t) * 0.45 + 0.5) * this.canvas.width;\n\
  var y = (Math.cos(t * 0.9) * 0.45 + 0.5) * this.canvas.height;\n\
  context.arc(x, y, 16, 0, 2 * Math.PI, false);\n\
  context.closePath();\n\
  context.fill();\n\
}\n\
\n\
function renderTestPatternLoop() {\n\
  updateTestPattern();\n\
  requestAnimationFrame(renderTestPatternLoop);\n\
}\n\
renderTestPatternLoop();\n\
\n' +
script + '\n\
</script></html>';
}
// setFillColor() to expose changes to its internal state.
setFillColor() to expose changes to its internal state.
setFillColor () to expose changes to its internal state .
function makeOffscreenTabTestDocument(script) {
  return '\
<html><body style="background-color:black; margin:0; padding:0;"></body>\n\
<script>\n\
var redColor = [255, 0, 0];\n\
var greenColor = [0, 255, 0];\n\
var blueColor = [0, 0, 255];\n\
\n\
var fillColor = [0, 0, 0];\n\
function setFillColor(color) {\n\
  fillColor = color;\n\
}\n\
\n\
var debugMessage = "";\n\
function setDebugMessage(msg) {\n\
  debugMessage = msg;\n\
}\n\
\n\
function updateTestPattern() {\n\
  if (!this.canvas) {\n\
    this.canvas = document.createElement("canvas");\n\
    this.canvas.width = ' + width + ';\n\
    this.canvas.height = ' + height + ';\n\
    this.canvas.style.position = "absolute";\n\
    this.canvas.style.top = "0px";\n\
    this.canvas.style.left = "0px";\n\
    this.canvas.style.width = "100%";\n\
    this.canvas.style.height = "100%";\n\
    document.body.appendChild(this.canvas);\n\
  }\n\
  var context = this.canvas.getContext("2d");\n\
  // Fill with solid color.\n\
  context.fillStyle = "rgb(" + fillColor + ")";\n\
  context.fillRect(0, 0, this.canvas.width, this.canvas.height);\n\
  // Draw the circle that moves around the page.\n\
  var inverseColor =\n\
      [255 - fillColor[0], 255 - fillColor[1], 255 - fillColor[2]];\n\
  if (debugMessage) {\n\
    context.fillStyle = "rgb(" + inverseColor + ")";\n\
    context.font = "xx-small monospace";\n\
    context.fillText(debugMessage, 0, 0);\n\
  }\n\
  context.fillStyle = "rgba(" + inverseColor + ", 0.5)";\n\
  context.beginPath();\n\
  if (!this.frameNumber) {\n\
    this.frameNumber = 1;\n\
  } else {\n\
    ++this.frameNumber;\n\
  }\n\
  var i = this.frameNumber % 200;\n\
  var t = (this.frameNumber + 3000) * (0.01 + i / 8000.0);\n\
  var x = (Math.sin(t) * 0.45 + 0.5) * this.canvas.width;\n\
  var y = (Math.cos(t * 0.9) * 0.45 + 0.5) * this.canvas.height;\n\
  context.arc(x, y, 16, 0, 2 * Math.PI, false);\n\
  context.closePath();\n\
  context.fill();\n\
}\n\
\n\
function renderTestPatternLoop() {\n\
  updateTestPattern();\n\
  requestAnimationFrame(renderTestPatternLoop);\n\
}\n\
renderTestPatternLoop();\n\
\n' +
script + '\n\
</script></html>';
}
function makeOffscreenTabTestDocument ( script ) { return '\
<html><body style="background-color:black; margin:0; padding:0;"></body>\n\
<script>\n\
var redColor = [255, 0, 0];\n\
var greenColor = [0, 255, 0];\n\
var blueColor = [0, 0, 255];\n\
\n\
var fillColor = [0, 0, 0];\n\
function setFillColor(color) {\n\
  fillColor = color;\n\
}\n\
\n\
var debugMessage = "";\n\
function setDebugMessage(msg) {\n\
  debugMessage = msg;\n\
}\n\
\n\
function updateTestPattern() {\n\
  if (!this.canvas) {\n\
    this.canvas = document.createElement("canvas");\n\
    this.canvas.width = ' + width + ';\n\
    this.canvas.height = ' + height + ';\n\
    this.canvas.style.position = "absolute";\n\
    this.canvas.style.top = "0px";\n\
    this.canvas.style.left = "0px";\n\
    this.canvas.style.width = "100%";\n\
    this.canvas.style.height = "100%";\n\
    document.body.appendChild(this.canvas);\n\
  }\n\
  var context = this.canvas.getContext("2d");\n\
  // Fill with solid color.\n\
  context.fillStyle = "rgb(" + fillColor + ")";\n\
  context.fillRect(0, 0, this.canvas.width, this.canvas.height);\n\
  // Draw the circle that moves around the page.\n\
  var inverseColor =\n\
      [255 - fillColor[0], 255 - fillColor[1], 255 - fillColor[2]];\n\
  if (debugMessage) {\n\
    context.fillStyle = "rgb(" + inverseColor + ")";\n\
    context.font = "xx-small monospace";\n\
    context.fillText(debugMessage, 0, 0);\n\
  }\n\
  context.fillStyle = "rgba(" + inverseColor + ", 0.5)";\n\
  context.beginPath();\n\
  if (!this.frameNumber) {\n\
    this.frameNumber = 1;\n\
  } else {\n\
    ++this.frameNumber;\n\
  }\n\
  var i = this.frameNumber % 200;\n\
  var t = (this.frameNumber + 3000) * (0.01 + i / 8000.0);\n\
  var x = (Math.sin(t) * 0.45 + 0.5) * this.canvas.width;\n\
  var y = (Math.cos(t * 0.9) * 0.45 + 0.5) * this.canvas.height;\n\
  context.arc(x, y, 16, 0, 2 * Math.PI, false);\n\
  context.closePath();\n\
  context.fill();\n\
}\n\
\n\
function renderTestPatternLoop() {\n\
  updateTestPattern();\n\
  requestAnimationFrame(renderTestPatternLoop);\n\
}\n\
renderTestPatternLoop();\n\
\n' + script + '\n\
</script></html>' ; }
setFillColor() to expose changes to its internal state.
setFillColor () to expose changes to its internal state .