docs: function makeDebugContext(ctx, opt_onErrorFunc, opt_onFunc) {
    init(ctx);
    opt_onErrorFunc = opt_onErrorFunc || function(err, functionName, args) {
          // apparently we can't do args.join(",");
          var argStr = "";
          for (var ii = 0; ii < args.length; ++ii) {
            argStr += ((ii == 0) ? '' : ', ') +
                glFunctionArgToString(functionName, ii, args[ii]);
          }
          error("WebGL error "+ glEnumToString(err) + " in "+ functionName +
                "(" + argStr + ")");
        };
  
    // Holds booleans for each GL error so after we get the error ourselves
    // we can still return it to the client app.
    var glErrorShadow = { };
  
    // Makes a function that calls a WebGL function and then calls getError.
    function makeErrorWrapper(ctx, functionName) {
      return function() {
        if (opt_onFunc) {
          opt_onFunc(functionName, arguments);
        }
        var result = ctx[functionName].apply(ctx, arguments);
        var err = ctx.getError();
        if (err != 0) {
          glErrorShadow[err] = true;
          opt_onErrorFunc(err, functionName, arguments);
        }
        return result;
      };
    }
  
    // Make a an object that has a copy of every property of the WebGL context
    // but wraps all functions.
    var wrapper = {};
    for (var propertyName in ctx) {
      if (typeof ctx[propertyName] == 'function') {
         wrapper[propertyName] = makeErrorWrapper(ctx, propertyName);
       } else {
         makePropertyWrapper(wrapper, ctx, propertyName);
       }
    }
  
    // Override the getError function with one that returns our saved results.
    wrapper.getError = function() {
      for (var err in glErrorShadow) {
        if (glErrorShadow.hasOwnProperty(err)) {
          if (glErrorShadow[err]) {
            glErrorShadow[err] = false;
            return err;
          }
        }
      }
      return ctx.NO_ERROR;
    };
  
    return wrapper;
  }