<commit_before>const CDP = require('chrome-remote-interface');
const fs = require('fs');

class ChromePageObject {

  constructor() {
    this.path = __dirname + '/binary';
  }

  getCDP() {
    return new Promise((resolve) => {
      if (!this._client) {
        CDP((client) => {
          this._client = client;
          resolve(client);
        }).on('error', (err) => {
          console.error("CDP Error: " + err.stack);
        });
      } else {
        resolve(this._client);
      }
    })
  }

  open(url, cb) {
    this.getCDP().then(async (client) => {
      const { Page } = client;
      try {
        await Page.enable();
        await Page.navigate({url: url});
        await Page.loadEventFired();
        cb(null, url)
      } catch (err) {
        cb(err, null);
        console.error(err);
      }
    });
  }

  async render(filePath) {
    this.getCDP().then(async (client) => {
      const { Page } = client;
      try {
        const { data } = await Page.captureScreenshot();
        fs.writeFileSync(filePath, Buffer.from(data, 'base64'));
      } catch (err) {
        console.error(err);
      }
    });
  }

  evaluate(fn, cb, ...args) {
    this.getCDP().then(async (client) => {
      const { Page, Runtime } = client;
      try {
        let executor = (stringyFunc, args) => {
          let invoke = new Function(
            "return " + stringyFunc
          )();
          return invoke.apply(null, args)
        }
        let executorString = `(${executor})(${fn.toString()}, ${JSON.stringify(args)})`
        await Runtime.enable();
        const { result: { value } } = await Runtime.evaluate({expression: executorString});
        cb (null, value);
      } catch (err) {
        cb(err, null);
        console.error(err);
      }
    });
  }

  goForward() {
    this.getCDP().then(async (client) => {
      const { Page } = client;
      try {
          await Page.enable();
          let {currentIndex, entries} = await Page.getNavigationHistory();
          if (currentIndex === entries.length-1) {
            return;
          } else {
            await Page.navigate({url: entries[currentIndex+1].url});
          }
      } catch (err) {
          console.error(err);
      }
    });
  }

  goBack() {
    this.getCDP().then(async (client) => {
      const { Page } = client;
      try {
        await Page.enable();
        let {currentIndex, entries} = await Page.getNavigationHistory();
        if (currentIndex === 0) {
          return;
        } else {
          await Page.navigate({url: entries[currentIndex-1].url});
        }
      } catch (err) {
        console.error(err);
      }
    });
  }

  injectJs(scriptPath) {
    const js = fs.readFileSync(scriptPath, {encoding: 'utf8'});
    this.getCDP().then(async (client) => {
      const { Page, Runtime } = client;
      try {
        await Runtime.enable();
        await Page.enable();
        await Page.loadEventFired();
        const result = await Runtime.evaluate({ expression: js });
      } catch (err) {
        console.error(err);
      }
    });
  }

  close() {
    this.getCDP().then(async (client) => {
      await client.close();
    });
  }
}

const page = new ChromePageObject();
module.exports = page;
<commit_msg>Proper handling of evaluate arguments<commit_after>const CDP = require('chrome-remote-interface');
const fs = require('fs');

class ChromePageObject {

  constructor() {
    this.path = __dirname + '/binary';
  }

  getCDP() {
    return new Promise((resolve) => {
      if (!this._client) {
        CDP((client) => {
          this._client = client;
          resolve(client);
        }).on('error', (err) => {
          console.error("CDP Error: " + err.stack);
        });
      } else {
        resolve(this._client);
      }
    })
  }

  open(url, cb) {
    this.getCDP().then(async (client) => {
      const { Page } = client;
      try {
        await Page.enable();
        await Page.navigate({url: url});
        await Page.loadEventFired();
        cb(null, url)
      } catch (err) {
        cb(err, null);
        console.error(err);
      }
    });
  }

  async render(filePath) {
    this.getCDP().then(async (client) => {
      const { Page } = client;
      try {
        const { data } = await Page.captureScreenshot();
        fs.writeFileSync(filePath, Buffer.from(data, 'base64'));
      } catch (err) {
        console.error(err);
      }
    });
  }

  evaluate(fn, ...args) {
    this.getCDP().then(async (client) => {
      const { Page, Runtime } = client;
      try {
        const cb = args.pop();
        let executor = (stringyFunc, args) => {
          let invoke = new Function(
            "return " + stringyFunc
          )();
          return invoke.apply(null, args)
        }
        let executorString = `(${executor})(${fn.toString()}, ${JSON.stringify(args)})`
        await Runtime.enable();
        const { result: { value } } = await Runtime.evaluate({expression: executorString});
        cb (null, value);
      } catch (err) {
        cb(err, null);
        console.error(err);
      }
    });
  }

  goForward() {
    this.getCDP().then(async (client) => {
      const { Page } = client;
      try {
          await Page.enable();
          let {currentIndex, entries} = await Page.getNavigationHistory();
          if (currentIndex === entries.length-1) {
            return;
          } else {
            await Page.navigate({url: entries[currentIndex+1].url});
          }
      } catch (err) {
          console.error(err);
      }
    });
  }

  goBack() {
    this.getCDP().then(async (client) => {
      const { Page } = client;
      try {
        await Page.enable();
        let {currentIndex, entries} = await Page.getNavigationHistory();
        if (currentIndex === 0) {
          return;
        } else {
          await Page.navigate({url: entries[currentIndex-1].url});
        }
      } catch (err) {
        console.error(err);
      }
    });
  }

  injectJs(scriptPath) {
    const js = fs.readFileSync(scriptPath, {encoding: 'utf8'});
    this.getCDP().then(async (client) => {
      const { Page, Runtime } = client;
      try {
        await Runtime.enable();
        await Page.enable();
        await Page.loadEventFired();
        const result = await Runtime.evaluate({ expression: js });
      } catch (err) {
        console.error(err);
      }
    });
  }

  close() {
    this.getCDP().then(async (client) => {
      await client.close();
    });
  }
}

const page = new ChromePageObject();
module.exports = page;

{'fraction_non_alphanumeric': 0.15965743997553142, 'fraction_numerical': 0.0021410001529285822, 'mean_word_length': 1.9027962716378162, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '578250', 'n_tokens_mistral': 2019, 'n_tokens_neox': 2012, 'n_words': 408}