docs: private static void replace_glob(GlobData rdata, Context cx,
                                       Scriptable scope, RegExpImpl reImpl,
                                       int leftIndex, int leftlen)
      {
          int replen;
          String lambdaStr;
          if (rdata.lambda != null) {
              // invoke lambda function with args lastMatch, $1, $2, ... $n,
              // leftContext.length, whole string.
              SubString[] parens = reImpl.parens;
              int parenCount = (parens == null) ? 0 : parens.length;
              Object[] args = new Object[parenCount + 3];
              args[0] = reImpl.lastMatch.toString();
              for (int i=0; i < parenCount; i++) {
                  SubString sub = parens[i];
                  if (sub != null) {
                      args[i+1] = sub.toString();
                  } else {
                      args[i+1] = Undefined.instance;
                  }
              }
              args[parenCount+1] = Integer.valueOf(reImpl.leftContext.length);
              args[parenCount+2] = rdata.str;
              // This is a hack to prevent expose of reImpl data to
              // JS function which can run new regexps modifing
              // regexp that are used later by the engine.
              // TODO: redesign is necessary
              if (reImpl != ScriptRuntime.getRegExpProxy(cx)) Kit.codeBug();
              RegExpImpl re2 = new RegExpImpl();
              re2.multiline = reImpl.multiline;
              re2.input = reImpl.input;
              ScriptRuntime.setRegExpProxy(cx, re2);
              try {
                  Scriptable parent = ScriptableObject.getTopLevelScope(scope);
                  Object result = rdata.lambda.call(cx, parent, parent, args);
                  lambdaStr = ScriptRuntime.toString(result);
              } finally {
                  ScriptRuntime.setRegExpProxy(cx, reImpl);
              }
              replen = lambdaStr.length();
          } else {
              lambdaStr = null;
              replen = rdata.repstr.length();
              if (rdata.dollar >= 0) {
                  int[] skip = new int[1];
                  int dp = rdata.dollar;
                  do {
                      SubString sub = interpretDollar(cx, reImpl, rdata.repstr,
                                                      dp, skip);
                      if (sub != null) {
                          replen += sub.length - skip[0];
                          dp += skip[0];
                      } else {
                          ++dp;
                      }
                      dp = rdata.repstr.indexOf('$', dp);
                  } while (dp >= 0);
              }
          }
  
          int growth = leftlen + replen + reImpl.rightContext.length;
          StringBuilder charBuf = rdata.charBuf;
          if (charBuf == null) {
              charBuf = new StringBuilder(growth);
              rdata.charBuf = charBuf;
          } else {
              charBuf.ensureCapacity(rdata.charBuf.length() + growth);
          }
  
          charBuf.append(reImpl.leftContext.str, leftIndex, leftIndex + leftlen);
          if (rdata.lambda != null) {
              charBuf.append(lambdaStr);
          } else {
              do_replace(rdata, cx, reImpl);
          }
      }