canvg vs canvas (v8)

Revision 8 of this benchmark created by Kerry Liu on


Description

Testing for string parsing overhead.

Preparation HTML

<script type="text/javascript" src="http://canvg.googlecode.com/svn/trunk/rgbcolor.js">
</script>
<script type="text/javascript" src="http://canvg.googlecode.com/svn/trunk/canvg.js">
</script>
<canvas id="test" />

Setup

var canvas = document.getElementById("test");
    canvas.width = 500;
    canvas.height = 500;
    var ctx = canvas.getContext("2d");
    ctx.translate(50, 50);

Test runner

Ready to run.

Testing in
TestOps/sec
canvg
// async test
canvg(canvas, '<svg height="100" viewBox="0 0 80 100" width="80" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="none"> <g id="Layer_0"> <rect id="rect3060" width="80" height="100" fill="none"/> <path fill="orange" id="path3062" d="M2.049,24.035c1.923,1.648,0,2.752,0,2.752s0,13.95,0,16.257c1.777,1.244,0,2.645,0,2.645v16.258l-2.049,1.496,63.646,36.557,16.354-9.09-1.378-1.886v-16.257s-2.268-0.64,0-2.89c-0.028-0.948,0-16.257,0-16.257s-1.464-0.812,0-2.109v-15.753l-14.423-8.282s-3.159,1.003-2.829-1.625c-1.251-0.718-16.427-9.434-28.817-16.548-1.081,0.492-3.017,1.074-2.646-1.52-7.595-4.351-13.553-7.783-13.553-7.783l-14.305,7.778v16.257z"/> </g> <g id="Layer_1"> <rect id="rect3065" width="80" height="100" fill="none"/> <polygon id="polygon3067" points="2.049,26.787,2.049,43.044,31.5,59.79,31.5,43.531" fill="#CCC"/> <polygon id="polygon3069" points="33.951,44.797,33.951,61.054,64.276,78.204,64.276,61.946" fill="#CCC"/> <polygon id="polygon3071" points="18.05,55.423,18.05,71.104,47.426,87.55,47.426,71.681" fill="#CCC"/> <polygon id="polygon3073" points="18.05,17.318,18.05,33.575,46.739,49.834,46.739,33.575" fill="#CCC"/> <polygon id="polygon3075" points="2.049,45.688,2.049,61.946,16.395,70.273,16.395,54.016" fill="#CCC"/> <polygon id="polygon3077" points="2.049,7.778,2.049,24.035,15.908,32.086,15.908,16.04" fill="#CCC"/> <polygon id="polygon3079" points="49.932,72.767,49.932,89.024,64.276,97.352,64.276,81.093" fill="#CCC"/> <polygon id="polygon3081" points="78.622,72.767,78.622,89.024,64.276,97.352,64.276,81.093" fill="#888"/> <polygon id="polygon3083" points="78.622,35.758,78.622,51.511,64.276,59.839,64.276,43.58" fill="#888"/> <polygon id="polygon3085" points="78.622,53.62,78.622,69.877,64.276,78.204,64.276,61.946" fill="#888"/> <polygon id="polygon3087" points="49.932,35.254,49.932,51.511,64.276,59.839,64.276,43.58" fill="#CCC"/> <polygon id="polygon3089" points="2.049,7.778,16.354,0,29.898,7.778,15.908,16.04" fill="#B3B3B3"/> <polygon id="polygon3091" points="18.05,17.318,32.546,9.299,61.206,25.758,46.739,33.575" fill="#B3B3B3"/> <polygon id="polygon3093" points="49.932,35.254,64.276,27.523,78.622,35.758,64.21,43.779" fill="#B3B3B3"/> <path id="path3095" d="M26.425,66.729c-0.648-11.04-10.101-20.648-7.502-29.426-16.474,8.521-15.64,21.693-12.527,30.628,12.915,27.827,20.777,11.552,20.029-1.202z" fill="url(#SVGIDfirewall_1_)"/> <path id="path3097" d="M39.284,73.648c-2.177-11.359,5.936-23.978-10.925-51.894,2.856,28.772-14.885,43.455-9.103,58.592,8.7,19.654,22.356,5.445,20.028-6.698z" fill="url(#SVGIDfirewall_2_)"/> <path id="path3099" d="M49.897,75.963c1.95-10.891-8.075-33.294-5.477-42.071-8.519,27.239-26.56,36.545-17.2,56.098,15.664,8.771,20.393-1.273,22.677-14.027z" fill="url(#SVGIDfirewall_3_)"/> <path id="path3101" d="M46.094,93.299c9.275-3.214,12.471-13.479,14.785-19.343-17.408,12.734-36.032-0.906-36.283,9.229-1.05,10.2,14.293,12.61,21.498,10.114z" fill="url(#SVGIDfirewall_4_)"/> </g> <defs id="defs3103"><linearGradient id="SVGIDfirewall_1_" xlink:actuate="onLoad" xlink:show="other" y1="60.254" y2="60.254" gradientUnits="userSpaceOnUse" xlink:type="simple" x2="26.474" x1="4.5986"> <stop id="stop3106" stop-color="#FF1600" offset="0"/> <stop id="stop3108" stop-color="#000" offset="1"/> </linearGradient><linearGradient id="SVGIDfirewall_2_" xlink:actuate="onLoad" xlink:show="other" y1="55.92" y2="55.92" gradientUnits="userSpaceOnUse" xlink:type="simple" x2="39.547" x1="18.09"> <stop id="stop3111" stop-color="#FF1600" offset="0"/> <stop id="stop3113" stop-color="#000" offset="1"/> </linearGradient><linearGradient id="SVGIDfirewall_3_" xlink:actuate="onLoad" xlink:show="other" y1="63.596" y2="63.596" gradientUnits="userSpaceOnUse" xlink:type="simple" x2="50.151" x1="24.596"> <stop id="stop3116" stop-color="#FF1600" offset="0"/> <stop id="stop3118" stop-color="#000" offset="1"/> </linearGradient><linearGradient id="SVGIDfirewall_4_" xlink:actuate="onLoad" xlink:show="other" y1="68.556" y2="68.556" gradientUnits="userSpaceOnUse" xlink:type="simple" gradientTransform="matrix(0.4056 0.914 -0.914 0.4056 86.0182 8.5152)" x2="61.363" x1="40.908"> <stop id="stop3121" stop-color="#FF1600" offset="0"/> <stop id="stop3123" stop-color="#000" offset="1"/> </linearGradient> </defs> </svg>', {
  ignoreMouse: true,
  ignoreAnimation: true,
  ignoreDimensions: true,
  renderCallback: function() {
     deferred.resolve();
  }
  
});
ready
generated canvas
data = {};
data.width = 80;
data.height = 100;
data.viewbox_width = 100;
data.viewbox_height = 100;
data.stroke_linejoin = "butt";
data.stroke_width = 2.0;
data.opacity = 1.0;
data.stroke = "black";
data.fill = "orange";
data.rx = 3;
data.ry = 3;
data.gradient = true;
data.stop_color_1 = data.fill;
data.stop_color_2 = "#FFFFFF";

ctx.save();
ctx.strokeStyle = 'rgba(0,0,0,0)';
ctx.lineCap = 'butt';
ctx.lineJoin = 'miter';
ctx.miterLimit = 10.0;
ctx.font = '10px sans-serif';
ctx.save();
ctx.strokeStyle = 'rgba(0,0,0,0)';
ctx.lineCap = 'butt';
ctx.lineJoin = 'miter';
ctx.miterLimit = 10.0;
ctx.font = '10px sans-serif';
ctx.beginPath();
ctx.moveTo(0E0, 0E0);
ctx.lineTo(data.width, 0E0);
ctx.lineTo(data.width, data.height);
ctx.lineTo(0E0, data.height);
ctx.closePath();
ctx.clip();
ctx.translate(-(Math.min((data.width / 8E1), (data.height / 1E2))) * 0E0, -(Math.min((data.width / 8E1), (data.height / 1E2))) * 0E0);
ctx.scale((data.width / 8E1), (data.height / 1E2));
ctx.save();
ctx.font = '10px sans-serif';
ctx.save();
ctx.fillStyle = 'rgba(0,0,0,0)';
ctx.font = '10px sans-serif';
ctx.beginPath();
ctx.moveTo(0E0, 0E0);
ctx.lineTo(8E1, 0E0);
ctx.quadraticCurveTo(8E1, 0E0, 8E1, 0E0);
ctx.lineTo(8E1, 1E2);
ctx.quadraticCurveTo(8E1, 1E2, 8E1, 1E2);
ctx.lineTo(0E0, 1E2);
ctx.quadraticCurveTo(0E0, 1E2, 0E0, 1E2);
ctx.lineTo(0E0, 0E0);
ctx.quadraticCurveTo(0E0, 0E0, 0E0, 0E0);
ctx.closePath();
ctx.fill();
ctx.stroke();
ctx.restore();
ctx.save();
ctx.fillStyle = (data.fill === 'none') ? 'rgba(0,0,0,0)' : data.fill;
ctx.font = '10px sans-serif';
ctx.beginPath();
ctx.moveTo(2.049E0, 2.4035E1);
ctx.bezierCurveTo(3.972E0, 2.5683E1, 2.049E0, 2.6787E1, 2.049E0, 2.6787E1);
ctx.bezierCurveTo(2.049E0, 2.6787E1, 2.049E0, 4.0737E1, 2.049E0, 4.3044E1);
ctx.bezierCurveTo(3.826E0, 4.4288E1, 2.049E0, 4.5689E1, 2.049E0, 4.5689E1);
ctx.lineTo(2.049E0, 6.1947E1);
ctx.lineTo(0E0, 6.3443E1);
ctx.lineTo(6.3646E1, 1E2);
ctx.lineTo(8E1, 9.091E1);
ctx.lineTo(7.8622E1, 8.9024E1);
ctx.lineTo(7.8622E1, 7.2767E1);
ctx.bezierCurveTo(7.8622E1, 7.2767E1, 7.6354E1, 7.2127E1, 7.8622E1, 6.9877E1);
ctx.bezierCurveTo(7.8594E1, 6.8929E1, 7.8622E1, 5.362E1, 7.8622E1, 5.362E1);
ctx.bezierCurveTo(7.8622E1, 5.362E1, 7.7158E1, 5.2808E1, 7.8622E1, 5.1511E1);
ctx.lineTo(7.8622E1, 3.5758E1);
ctx.lineTo(6.4199E1, 2.7476E1);
ctx.bezierCurveTo(6.4199E1, 2.7476E1, 6.104E1, 2.8479E1, 6.137E1, 2.5851E1);
ctx.bezierCurveTo(6.0119E1, 2.5133E1, 4.4943E1, 1.6417E1, 3.2553E1, 9.303E0);
ctx.bezierCurveTo(3.1472E1, 9.795E0, 2.9536E1, 1.0377E1, 2.9907E1, 7.783E0);
ctx.bezierCurveTo(2.2312E1, 3.432E0, 1.6354E1, (-9.769963E-15), 1.6354E1, (-9.769963E-15));
ctx.lineTo(2.049E0, 7.778E0);
ctx.lineTo(2.049E0, 2.4035E1);
ctx.closePath();
ctx.fill();
ctx.stroke();
ctx.restore();
ctx.restore();
ctx.save();
ctx.font = '10px sans-serif';
ctx.save();
ctx.fillStyle = 'rgba(0,0,0,0)';
ctx.font = '10px sans-serif';
ctx.beginPath();
ctx.moveTo(0E0, 0E0);
ctx.lineTo(8E1, 0E0);
ctx.quadraticCurveTo(8E1, 0E0, 8E1, 0E0);
ctx.lineTo(8E1, 1E2);
ctx.quadraticCurveTo(8E1, 1E2, 8E1, 1E2);
ctx.lineTo(0E0, 1E2);
ctx.quadraticCurveTo(0E0, 1E2, 0E0, 1E2);
ctx.lineTo(0E0, 0E0);
ctx.quadraticCurveTo(0E0, 0E0, 0E0, 0E0);
ctx.closePath();
ctx.fill();
ctx.stroke();
ctx.restore();
ctx.save();
ctx.fillStyle = '#CCC';
ctx.font = '10px sans-serif';
ctx.beginPath();
ctx.moveTo(2.049E0, 2.6787E1);
ctx.lineTo(2.049E0, 4.3044E1);
ctx.lineTo(3.15E1, 5.979E1);
ctx.lineTo(3.15E1, 4.3531E1);
ctx.lineTo(2.049E0, 2.6787E1);
ctx.closePath();
ctx.fill();
ctx.stroke();
ctx.restore();
ctx.save();
ctx.fillStyle = '#CCC';
ctx.font = '10px sans-serif';
ctx.beginPath();
ctx.moveTo(3.3951E1, 4.4797E1);
ctx.lineTo(3.3951E1, 6.1054E1);
ctx.lineTo(6.4276E1, 7.8204E1);
ctx.lineTo(6.4276E1, 6.1946E1);
ctx.lineTo(3.3951E1, 4.4797E1);
ctx.closePath();
ctx.fill();
ctx.stroke();
ctx.restore();
ctx.save();
ctx.fillStyle = '#CCC';
ctx.font = '10px sans-serif';
ctx.beginPath();
ctx.moveTo(1.805E1, 5.5423E1);
ctx.lineTo(1.805E1, 7.1104E1);
ctx.lineTo(4.7426E1, 8.755E1);
ctx.lineTo(4.7426E1, 7.1681E1);
ctx.lineTo(1.805E1, 5.5423E1);
ctx.closePath();
ctx.fill();
ctx.stroke();
ctx.restore();
ctx.save();
ctx.fillStyle = '#CCC';
ctx.font = '10px sans-serif';
ctx.beginPath();
ctx.moveTo(1.805E1, 1.7318E1);
ctx.lineTo(1.805E1, 3.3575E1);
ctx.lineTo(4.6739E1, 4.9834E1);
ctx.lineTo(4.6739E1, 3.3575E1);
ctx.lineTo(1.805E1, 1.7318E1);
ctx.closePath();
ctx.fill();
ctx.stroke();
ctx.restore();
ctx.save();
ctx.fillStyle = '#CCC';
ctx.font = '10px sans-serif';
ctx.beginPath();
ctx.moveTo(2.049E0, 4.5688E1);
ctx.lineTo(2.049E0, 6.1946E1);
ctx.lineTo(1.6395E1, 7.0273E1);
ctx.lineTo(1.6395E1, 5.4016E1);
ctx.lineTo(2.049E0, 4.5688E1);
ctx.closePath();
ctx.fill();
ctx.stroke();
ctx.restore();
ctx.save();
ctx.fillStyle = '#CCC';
ctx.font = '10px sans-serif';
ctx.beginPath();
ctx.moveTo(2.049E0, 7.778E0);
ctx.lineTo(2.049E0, 2.4035E1);
ctx.lineTo(1.5908E1, 3.2086E1);
ctx.lineTo(1.5908E1, 1.604E1);
ctx.lineTo(2.049E0, 7.778E0);
ctx.closePath();
ctx.fill();
ctx.stroke();
ctx.restore();
ctx.save();
ctx.fillStyle = '#CCC';
ctx.font = '10px sans-serif';
ctx.beginPath();
ctx.moveTo(4.9932E1, 7.2767E1);
ctx.lineTo(4.9932E1, 8.9024E1);
ctx.lineTo(6.4276E1, 9.7352E1);
ctx.lineTo(6.4276E1, 8.1093E1);
ctx.lineTo(4.9932E1, 7.2767E1);
ctx.closePath();
ctx.fill();
ctx.stroke();
ctx.restore();
ctx.save();
ctx.fillStyle = '#888';
ctx.font = '10px sans-serif';
ctx.beginPath();
ctx.moveTo(7.8622E1, 7.2767E1);
ctx.lineTo(7.8622E1, 8.9024E1);
ctx.lineTo(6.4276E1, 9.7352E1);
ctx.lineTo(6.4276E1, 8.1093E1);
ctx.lineTo(7.8622E1, 7.2767E1);
ctx.closePath();
ctx.fill();
ctx.stroke();
ctx.restore();
ctx.save();
ctx.fillStyle = '#888';
ctx.font = '10px sans-serif';
ctx.beginPath();
ctx.moveTo(7.8622E1, 3.5758E1);
ctx.lineTo(7.8622E1, 5.1511E1);
ctx.lineTo(6.4276E1, 5.9839E1);
ctx.lineTo(6.4276E1, 4.358E1);
ctx.lineTo(7.8622E1, 3.5758E1);
ctx.closePath();
ctx.fill();
ctx.stroke();
ctx.restore();
ctx.save();
ctx.fillStyle = '#888';
ctx.font = '10px sans-serif';
ctx.beginPath();
ctx.moveTo(7.8622E1, 5.362E1);
ctx.lineTo(7.8622E1, 6.9877E1);
ctx.lineTo(6.4276E1, 7.8204E1);
ctx.lineTo(6.4276E1, 6.1946E1);
ctx.lineTo(7.8622E1, 5.362E1);
ctx.closePath();
ctx.fill();
ctx.stroke();
ctx.restore();
ctx.save();
ctx.fillStyle = '#CCC';
ctx.font = '10px sans-serif';
ctx.beginPath();
ctx.moveTo(4.9932E1, 3.5254E1);
ctx.lineTo(4.9932E1, 5.1511E1);
ctx.lineTo(6.4276E1, 5.9839E1);
ctx.lineTo(6.4276E1, 4.358E1);
ctx.lineTo(4.9932E1, 3.5254E1);
ctx.closePath();
ctx.fill();
ctx.stroke();
ctx.restore();
ctx.save();
ctx.fillStyle = '#B3B3B3';
ctx.font = '10px sans-serif';
ctx.beginPath();
ctx.moveTo(2.049E0, 7.778E0);
ctx.lineTo(1.6354E1, 0E0);
ctx.lineTo(2.9898E1, 7.778E0);
ctx.lineTo(1.5908E1, 1.604E1);
ctx.lineTo(2.049E0, 7.778E0);
ctx.closePath();
ctx.fill();
ctx.stroke();
ctx.restore();
ctx.save();
ctx.fillStyle = '#B3B3B3';
ctx.font = '10px sans-serif';
ctx.beginPath();
ctx.moveTo(1.805E1, 1.7318E1);
ctx.lineTo(3.2546E1, 9.299E0);
ctx.lineTo(6.1206E1, 2.5758E1);
ctx.lineTo(4.6739E1, 3.3575E1);
ctx.lineTo(1.805E1, 1.7318E1);
ctx.closePath();
ctx.fill();
ctx.stroke();
ctx.restore();
ctx.save();
ctx.fillStyle = '#B3B3B3';
ctx.font = '10px sans-serif';
ctx.beginPath();
ctx.moveTo(4.9932E1, 3.5254E1);
ctx.lineTo(6.4276E1, 2.7523E1);
ctx.lineTo(7.8622E1, 3.5758E1);
ctx.lineTo(6.421E1, 4.3779E1);
ctx.lineTo(4.9932E1, 3.5254E1);
ctx.closePath();
ctx.fill();
ctx.stroke();
ctx.restore();
ctx.save();
var linearGradient = ctx.createLinearGradient(4.5986E0, 6.0254E1, 2.6474E1, 6.0254E1);
linearGradient.addColorStop(0E0, '#FF1600');
linearGradient.addColorStop(1E0, '#000');
ctx.fillStyle = linearGradient;
ctx.font = '10px sans-serif';
ctx.beginPath();
ctx.moveTo(2.6425E1, 6.6729E1);
ctx.bezierCurveTo(2.5777E1, 5.5689E1, 1.6324E1, 4.6081E1, 1.8923E1, 3.7303E1);
ctx.bezierCurveTo(2.449E0, 4.5824E1, 3.283E0, 5.8996E1, 6.396E0, 6.7931E1);
ctx.bezierCurveTo(1.9311E1, 9.5758E1, 2.7173E1, 7.9483E1, 2.6425E1, 6.6729E1);
ctx.closePath();
ctx.fill();
ctx.stroke();
ctx.restore();
ctx.save();
var linearGradient = ctx.createLinearGradient(1.809E1, 5.592E1, 3.9547E1, 5.592E1);
linearGradient.addColorStop(0E0, '#FF1600');
linearGradient.addColorStop(1E0, '#000');
ctx.fillStyle = linearGradient;
ctx.font = '10px sans-serif';
ctx.beginPath();
ctx.moveTo(3.9284E1, 7.3648E1);
ctx.bezierCurveTo(3.7107E1, 6.2289E1, 4.522E1, 4.967E1, 2.8359E1, 2.1754E1);
ctx.bezierCurveTo(3.1215E1, 5.0526E1, 1.3474E1, 6.5209E1, 1.9256E1, 8.0346E1);
ctx.bezierCurveTo(2.7956E1, 1E2, 4.1612E1, 8.5791E1, 3.9284E1, 7.3648E1);
ctx.closePath();
ctx.fill();
ctx.stroke();
ctx.restore();
ctx.save();
var linearGradient = ctx.createLinearGradient(2.4596E1, 6.3596E1, 5.0151E1, 6.3596E1);
linearGradient.addColorStop(0E0, '#FF1600');
linearGradient.addColorStop(1E0, '#000');
ctx.fillStyle = linearGradient;
ctx.font = '10px sans-serif';
ctx.beginPath();
ctx.moveTo(4.9897E1, 7.5963E1);
ctx.bezierCurveTo(5.1847E1, 6.5072E1, 4.1822E1, 4.2669E1, 4.442E1, 3.3892E1);
ctx.bezierCurveTo(3.5901E1, 6.1131E1, 1.786E1, 7.0437E1, 2.722E1, 8.999E1);
ctx.bezierCurveTo(4.2884E1, 9.8761E1, 4.7613E1, 8.8717E1, 4.9897E1, 7.5963E1);
ctx.closePath();
ctx.fill();
ctx.stroke();
ctx.restore();
ctx.save();
var linearGradient = ctx.createLinearGradient(4.0908E1, 6.8556E1, 6.1363E1, 6.8556E1);
linearGradient.addColorStop(0E0, '#FF1600');
linearGradient.addColorStop(1E0, '#000');
if (8E1 > 0.0 && 1E2 > 0.0) {
  var c = document.createElement('canvas');
  c.width = 8E1;
  c.height = 1E2;
  var tmpCtx = c.getContext('2d');
  data.transform_gradient_fill = linearGradient;
  tmpCtx.save();
  tmpCtx.strokeStyle = 'rgba(0,0,0,0)';
  tmpCtx.lineCap = 'butt';
  tmpCtx.lineJoin = 'miter';
  tmpCtx.miterLimit = 10.0;
  tmpCtx.font = '10px sans-serif';
  tmpCtx.translate(0E0, 0E0);
  tmpCtx.save();
  tmpCtx.font = '10px sans-serif';
  tmpCtx.transform(4.056E-1, 9.14E-1, (-9.14E-1), 4.056E-1, 8.60182E1, 8.5152E0);
  tmpCtx.save();
  tmpCtx.fillStyle = (data.transform_gradient_fill === 'none') ? 'rgba(0,0,0,0)' : data.transform_gradient_fill;
  tmpCtx.font = '10px sans-serif';
  tmpCtx.beginPath();
  tmpCtx.moveTo((-1E4), (-1E4));
  tmpCtx.lineTo(2E4, (-1E4));
  tmpCtx.quadraticCurveTo(2E4, (-1E4), 2E4, (-1E4));
  tmpCtx.lineTo(2E4, 2E4);
  tmpCtx.quadraticCurveTo(2E4, 2E4, 2E4, 2E4);
  tmpCtx.lineTo((-1E4), 2E4);
  tmpCtx.quadraticCurveTo((-1E4), 2E4, (-1E4), 2E4);
  tmpCtx.lineTo((-1E4), (-1E4));
  tmpCtx.quadraticCurveTo((-1E4), (-1E4), (-1E4), (-1E4));
  tmpCtx.closePath();
  tmpCtx.fill();
  tmpCtx.stroke();
  tmpCtx.restore();
  tmpCtx.restore();
  tmpCtx.restore();
  linearGradient = tmpCtx.createPattern(c, 'no-repeat');
}
ctx.fillStyle = linearGradient;
ctx.font = '10px sans-serif';
ctx.beginPath();
ctx.moveTo(4.6094E1, 9.3299E1);
ctx.bezierCurveTo(5.5369E1, 9.0085E1, 5.8565E1, 7.982E1, 6.0879E1, 7.3956E1);
ctx.bezierCurveTo(4.3471E1, 8.669E1, 2.4847E1, 7.305E1, 2.4596E1, 8.3185E1);
ctx.bezierCurveTo(2.3546E1, 9.3385E1, 3.8889E1, 9.5795E1, 4.6094E1, 9.3299E1);
ctx.closePath();
ctx.fill();
ctx.stroke();
ctx.restore();
ctx.restore();
ctx.restore();
ctx.restore();
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.