diff --git a/add-on/lib/proxyblock.js b/add-on/lib/proxyblock.js index 2897879..74b7828 100644 --- a/add-on/lib/proxyblock.js +++ b/add-on/lib/proxyblock.js @@ -104,10 +104,22 @@ } }; + // Every time the proxy has been called 1000 times, return + // undefined instead of the proxy object, to ensure that the + // proxy doesn't get stuck in an infinite loop. + let recursionGuardCounter = 0; + const blockingProxy = new Proxy(defaultFunction, { get: function (ignore, property) { logKeyPath(); + if (recursionGuardCounter === 1000) { + recursionGuardCounter = 0; + return undefined; + } + + recursionGuardCounter += 1; + if (property === Symbol.toPrimitive) { return toPrimitiveFunc; } diff --git a/gulpfile.js b/gulpfile.js index 4a5e271..b32caea 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -15,7 +15,13 @@ gulp.task("default", function () { } const fileContents = fs.readFileSync(standardsDefDir + "/" + next, {encoding: "utf8"}); - const standardContents = JSON.parse(fileContents); + let standardContents; + try { + standardContents = JSON.parse(fileContents); + } catch (e) { + console.log("Invalid JSON in " + next); + throw e; + } const stdName = standardContents.info.name; const stdSubName = standardContents.info.subsection_name; diff --git a/package.json b/package.json index 93111f4..ef82442 100644 --- a/package.json +++ b/package.json @@ -26,8 +26,9 @@ "firefox": "web-ext -s add-on run", "lint": "node_modules/eslint/bin/eslint.js .", "lint:fix": "node_modules/eslint/bin/eslint.js --fix .", - "test": "npm run clean; npm run bundle && ln -s `ls dist/` dist/webapi_manager.zip && cross-env node_modules/mocha/bin/mocha test/functional/*.js", - "test:watch": "cross-env npm test --watch" + "test": "npm run clean; npm run bundle && ln -s `ls dist/` dist/webapi_manager.zip && cross-env node_modules/mocha/bin/mocha test/functional/*.js --only-local-tests", + "test:watch": "cross-env npm test --watch", + "test:all": "npm run clean; npm run bundle && ln -s `ls dist/` dist/webapi_manager.zip && cross-env node_modules/mocha/bin/mocha test/functional/*.js" }, "pre-push": { "run": [ diff --git a/test/fixtures/infinite-loop.html b/test/fixtures/infinite-loop.html new file mode 100644 index 0000000..3ce4482 --- /dev/null +++ b/test/fixtures/infinite-loop.html @@ -0,0 +1,32 @@ + + + + + Testing Infinite Loop Case + + +
+

A child node

+
+ + + + diff --git a/test/functional/block.js b/test/functional/block.js index 1ac15df..c16ac36 100644 --- a/test/functional/block.js +++ b/test/functional/block.js @@ -3,6 +3,9 @@ const utils = require("./lib/utils"); const injected = require("./lib/injected"); const testServer = require("./lib/server"); +const webdriver = require("selenium-webdriver"); +const by = webdriver.By; +const until = webdriver.until; describe("Basic Functionality", function () { @@ -27,7 +30,7 @@ describe("Basic Functionality", function () { testUrl = url; httpServer = server; - + const standardsToBlock = []; let driverReference; @@ -54,10 +57,8 @@ describe("Basic Functionality", function () { it("SVG blocking", function (done) { - this.timeout = function () { - return 10000; - }; - + this.timeout = () => 10000; + const [server, url] = testServer.start(); testUrl = url; @@ -84,5 +85,34 @@ describe("Basic Functionality", function () { done(e); }); }); + + it("Proxyblock does not get stuck in infinite loop", function (done) { + + const [server, url] = testServer.startWithFile("infinite-loop.html"); + + testUrl = url; + httpServer = server; + + const standardsToBlock = ["Selectors API Level 1"]; + let driverReference; + + utils.promiseGetDriver() + .then(function (driver) { + driverReference = driver; + return utils.promiseSetBlockingRules(driver, standardsToBlock); + }) + .then(() => driverReference.get(testUrl)) + .then(() => driverReference.wait(until.elementLocated(by.css("div.success-case")), 2000)) + .then(function () { + driverReference.quit(); + testServer.stop(httpServer); + done(); + }) + .catch(function (e) { + driverReference.quit(); + testServer.stop(httpServer); + done(e); + }); + }); }); }); diff --git a/test/functional/lib/server.js b/test/functional/lib/server.js index ada3a23..04ee324 100644 --- a/test/functional/lib/server.js +++ b/test/functional/lib/server.js @@ -1,5 +1,7 @@ "use strict"; +const path = require("path"); +const fs = require("fs"); const http = require("http"); const testPort = 8989; @@ -34,6 +36,27 @@ module.exports.start = function (callback, html) { return [httpServer, testUrl]; }; +/** + * Starts the test server, serving the provided html file from the fixtures dir. + * + * @param {string} testHtmlFileName + * The name of the fixture file the test server should serve. + * @param {function|undefined} callback + * An optional callback function that, if provided, will be called with + * a single argument, an object describing which headers will be sent from + * the server. The callback function can modify this as needed. + * + * @return {array} + * An array of length two. The first item is the server object, and the + * second item is the absolute URL that the server is serving from. + */ +module.exports.startWithFile = function (testHtmlFileName, callback) { + + const pathToTestHtmlFileName = path.join(__dirname, "..", "..", "fixtures", testHtmlFileName); + const htmlFileContents = fs.readFileSync(pathToTestHtmlFileName, "utf8"); + return module.exports.start(callback, htmlFileContents); +}; + module.exports.stop = function (server) { server.close(); }; diff --git a/test/functional/lib/utils.js b/test/functional/lib/utils.js index 972a0e1..8de98f9 100644 --- a/test/functional/lib/utils.js +++ b/test/functional/lib/utils.js @@ -5,14 +5,16 @@ require("geckodriver"); const firefox = require("selenium-webdriver/firefox"); -const webdriver = require("selenium-webdriver"); const injectedScripts = require("./injected"); -const by = webdriver.By; const Context = firefox.Context; +const webdriver = require("selenium-webdriver"); +const by = webdriver.By; const until = webdriver.until; const keys = webdriver.Key; const path = require("path"); +module.exports.shouldRunRemoteTests = process.argv.indexOf("--only-local-tests") === -1; + module.exports.constants = { svgBlockRule: ["Scalable Vector Graphics (SVG) 1.1 (Second Edition)"] }; diff --git a/test/functional/logins.js b/test/functional/logins.js index bbcdb3a..ca4c804 100644 --- a/test/functional/logins.js +++ b/test/functional/logins.js @@ -13,8 +13,14 @@ const keys = webdriver.Key; const by = webdriver.By; const until = webdriver.until; + describe("Logging into popular sites", function () { + if (utils.shouldRunRemoteTests === false) { + // Skipping remote tests because of --only-local-tests flag + return; + } + describe("GitHub", function () { if (!testParams.github.username) {