diff --git a/CHANGELOG.md b/CHANGELOG.md index 7fce88179..72d1870c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [6.3.18](https://github.com/karma-runner/karma/compare/v6.3.17...v6.3.18) (2022-04-13) + + +### Bug Fixes + +* **deps:** upgrade socket.io to v4.4.1 ([52a30bb](https://github.com/karma-runner/karma/commit/52a30bbc6e168333a8592c26c9f40678d6ab74ea)) + ## [6.3.17](https://github.com/karma-runner/karma/compare/v6.3.16...v6.3.17) (2022-02-28) diff --git a/client/main.js b/client/main.js index 7dfc5b738..f8546ebb5 100644 --- a/client/main.js +++ b/client/main.js @@ -15,7 +15,7 @@ var socket = io(location.host, { reconnectionDelay: 500, reconnectionDelayMax: Infinity, timeout: BROWSER_SOCKET_TIMEOUT, - path: KARMA_PROXY_PATH + KARMA_URL_ROOT.substr(1) + 'socket.io', + path: KARMA_PROXY_PATH + KARMA_URL_ROOT.slice(1) + 'socket.io', 'sync disconnect on unload': true, useNativeTimers: true }) diff --git a/common/util.js b/common/util.js index 9d406c635..6c251a901 100644 --- a/common/util.js +++ b/common/util.js @@ -20,7 +20,7 @@ exports.isDefined = function (value) { exports.parseQueryParams = function (locationSearch) { var params = {} - var pairs = locationSearch.substr(1).split('&') + var pairs = locationSearch.slice(1).split('&') var keyValue for (var i = 0; i < pairs.length; i++) { diff --git a/docs/config/01-configuration-file.md b/docs/config/01-configuration-file.md index dff4b6135..dfa0bf1cd 100644 --- a/docs/config/01-configuration-file.md +++ b/docs/config/01-configuration-file.md @@ -53,6 +53,20 @@ module.exports = (config) => { } ``` +Alternatively, you can use an `async` function instead (since v6.3). + +```javascript +// karma.conf.js +module.exports = async (config) => { + const karmaConfig = await getKarmaConfig("dev"); + + config.set({ + ...karmaConfig + }); +}; +``` + + ### Customized TypeScript Configuration Under the hood Karma uses ts-node to transpile TypeScript to JavaScript. If the resolved `tsconfig.json` has `module` configured as `ES` formats. You might get errors like `SyntaxError: Unexpected token`. This is due that in Node `ES` module formats are not supported. To overcome this issue you need to configure ts-node to use `commonjs` module format. diff --git a/lib/completion.js b/lib/completion.js index 8e2d56f63..eb058527c 100644 --- a/lib/completion.js +++ b/lib/completion.js @@ -36,7 +36,7 @@ const options = { function opositeWord (word) { if (word.startsWith('-')) { - return word.startsWith('--no-') ? `--${word.substr(5)}` : `--no-${word.substr(2)}` + return word.startsWith('--no-') ? `--${word.slice(5)}` : `--no-${word.slice(2)}` } else { return null } diff --git a/lib/events.js b/lib/events.js index 6d8280bfc..7d64ce39d 100644 --- a/lib/events.js +++ b/lib/events.js @@ -35,7 +35,7 @@ class KarmaEventEmitter extends EventEmitter { bind (object) { for (const method in object) { if (method.startsWith('on') && helper.isFunction(object[method])) { - this.on(helper.camelToSnake(method.substr(2)), function () { + this.on(helper.camelToSnake(method.slice(2)), function () { // We do not use an arrow function here, to supply the caller as this. object[method].apply(object, Array.from(arguments).concat(this)) }) diff --git a/lib/file.js b/lib/file.js index 24e140779..2342fd3ab 100644 --- a/lib/file.js +++ b/lib/file.js @@ -36,7 +36,7 @@ class File { * @returns {string} detected file type or empty string */ detectType () { - return path.extname(this.path).substring(1) + return path.extname(this.path).slice(1) } toString () { diff --git a/lib/helper.js b/lib/helper.js index cd239ecc3..9be119378 100644 --- a/lib/helper.js +++ b/lib/helper.js @@ -30,15 +30,15 @@ const parser = (pattern, out) => { t = 'optional' } out[t]++ - return parser(pattern.substring(1), out) + return parser(pattern.slice(1), out) } if (matches[2] !== undefined) { out.ext_glob++ parser(matches[2], out) - return parser(pattern.substring(matches[0].length), out) + return parser(pattern.slice(matches[0].length), out) } out.range++ - return parser(pattern.substring(matches[0].length), out) + return parser(pattern.slice(matches[0].length), out) } const gsParser = (pattern, out) => { @@ -96,7 +96,7 @@ exports.camelToSnake = (camelCase) => { } exports.ucFirst = (word) => { - return word.charAt(0).toUpperCase() + word.substr(1) + return word.charAt(0).toUpperCase() + word.slice(1) } exports.dashToCamel = (dash) => { diff --git a/lib/launcher.js b/lib/launcher.js index 723390c09..e374fbbd1 100644 --- a/lib/launcher.js +++ b/lib/launcher.js @@ -60,7 +60,7 @@ class Launcher { protocol = upstreamProxy.protocol hostname = upstreamProxy.hostname port = upstreamProxy.port - urlRoot = upstreamProxy.path + urlRoot.substr(1) + urlRoot = upstreamProxy.path + urlRoot.slice(1) } return (name) => { diff --git a/lib/launchers/process.js b/lib/launchers/process.js index a7aa101ce..9fa859fc3 100644 --- a/lib/launchers/process.js +++ b/lib/launchers/process.js @@ -44,7 +44,7 @@ function ProcessLauncher (spawn, tempDir, timer, processKillTimeout) { // Normalize the command, remove quotes (spawn does not like them). this._normalizeCommand = function (cmd) { if (cmd.charAt(0) === cmd.charAt(cmd.length - 1) && '\'`"'.includes(cmd.charAt(0))) { - cmd = cmd.substring(1, cmd.length - 1) + cmd = cmd.slice(1, -1) log.warn(`The path should not be quoted.\n Normalized the path to ${cmd}`) } diff --git a/lib/middleware/karma.js b/lib/middleware/karma.js index 5f701e7e7..a5c94f399 100644 --- a/lib/middleware/karma.js +++ b/lib/middleware/karma.js @@ -32,9 +32,9 @@ const FILE_TYPES = [ function filePathToUrlPath (filePath, basePath, urlRoot, proxyPath) { if (filePath.startsWith(basePath)) { - return proxyPath + urlRoot.substr(1) + 'base' + filePath.substr(basePath.length) + return proxyPath + urlRoot.slice(1) + 'base' + filePath.slice(basePath.length) } - return proxyPath + urlRoot.substr(1) + 'absolute' + filePath + return proxyPath + urlRoot.slice(1) + 'absolute' + filePath } function getQuery (urlStr) { @@ -85,8 +85,8 @@ function createKarmaMiddleware ( const requestedRangeHeader = request.headers.range // redirect /__karma__ to /__karma__ (trailing slash) - if (requestUrl === urlRoot.substr(0, urlRoot.length - 1)) { - response.setHeader('Location', proxyPath + urlRoot.substr(1)) + if (requestUrl === urlRoot.slice(0, -1)) { + response.setHeader('Location', proxyPath + urlRoot.slice(1)) response.writeHead(301) return response.end('MOVED PERMANENTLY') } @@ -97,7 +97,7 @@ function createKarmaMiddleware ( } // remove urlRoot prefix - requestUrl = requestUrl.substr(urlRoot.length - 1) + requestUrl = requestUrl.slice(urlRoot.length - 1) // serve client.html if (requestUrl === '/') { diff --git a/lib/runner.js b/lib/runner.js index 7d07bb08b..2e04065b6 100644 --- a/lib/runner.js +++ b/lib/runner.js @@ -18,9 +18,9 @@ function parseExitCode (buffer, defaultExitCode, failOnEmptyTestSuite) { const tail = buffer.slice(tailPos) const tailStr = tail.toString() - if (tailStr.substr(0, tailStr.length - 2) === constant.EXIT_CODE) { - const emptyInt = parseInt(tailStr.substr(-2, 1), 10) - let exitCode = parseInt(tailStr.substr(-1), 10) + if (tailStr.slice(0, -2) === constant.EXIT_CODE) { + const emptyInt = parseInt(tailStr.slice(-2, -1), 10) + let exitCode = parseInt(tailStr.slice(-1), 10) if (failOnEmptyTestSuite === false && emptyInt === 0) { log.warn('Test suite was empty.') exitCode = 0 diff --git a/lib/url.js b/lib/url.js index 0bbfcc6d3..ebe078619 100644 --- a/lib/url.js +++ b/lib/url.js @@ -19,7 +19,7 @@ class Url { * @returns {string} detected file type or empty string */ detectType () { - return path.extname(new URL(this.path).pathname).substring(1) + return path.extname(new URL(this.path).pathname).slice(1) } toString () { diff --git a/package-lock.json b/package-lock.json index 7c46baedc..f230766d6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "karma", - "version": "6.3.17", + "version": "6.3.18", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1188,6 +1188,11 @@ "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", "dev": true }, + "@socket.io/base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@socket.io/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-dOlCBKnDw4iShaIsH/bxujKTM18+2TOAsYz+KSc11Am38H4q5Xw8Bbz97ZYdrVNM+um3p7w86Bvvmcn9q+5+eQ==" + }, "@tootallnate/once": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", @@ -1228,9 +1233,9 @@ "dev": true }, "@types/node": { - "version": "13.11.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-13.11.0.tgz", - "integrity": "sha512-uM4mnmsIIPK/yeO+42F2RQhGUIs39K2RFmugcJANppXe6J1nvH87PvzPZYpza7Xhhs8Yn9yIAVdLZ84z61+0xQ==" + "version": "17.0.23", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.23.tgz", + "integrity": "sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw==" }, "@types/normalize-package-data": { "version": "2.4.1", @@ -1261,12 +1266,27 @@ } }, "accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "requires": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "dependencies": { + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + } } }, "acorn": { @@ -1662,11 +1682,6 @@ } } }, - "base64-arraybuffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.1.tgz", - "integrity": "sha512-vFIUq7FdLtjZMhATwDul5RZWv2jpXQ09Pd6jcVEOvIsqCWTRFD/ONHNfyOS8dA/Ippi5dsIgpyKWKZaAKZltbA==" - }, "base64-js": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", @@ -2548,9 +2563,9 @@ } }, "cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==" + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" }, "cookiejar": { "version": "2.1.2", @@ -3179,9 +3194,9 @@ "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" }, "engine.io": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.0.0.tgz", - "integrity": "sha512-Ui7yl3JajEIaACg8MOUwWvuuwU7jepZqX3BKs1ho7NQRuP4LhN4XIykXhp8bEy+x/DhA0LBZZXYSCkZDqrwMMg==", + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.1.3.tgz", + "integrity": "sha512-rqs60YwkvWTLLnfazqgZqLa/aKo+9cueVfEi/dZ8PyGyaf8TLOxj++4QMIgeG3Gn0AhrWiFXvghsoY9L9h25GA==", "requires": { "@types/cookie": "^0.4.1", "@types/cors": "^2.8.12", @@ -3191,14 +3206,14 @@ "cookie": "~0.4.1", "cors": "~2.8.5", "debug": "~4.3.1", - "engine.io-parser": "~5.0.0", + "engine.io-parser": "~5.0.3", "ws": "~8.2.3" }, "dependencies": { "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "requires": { "ms": "2.1.2" } @@ -3211,11 +3226,11 @@ } }, "engine.io-parser": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.1.tgz", - "integrity": "sha512-j4p3WwJrG2k92VISM0op7wiq60vO92MlF3CRGxhKHy9ywG1/Dkc72g0dXeDQ+//hrcDn8gqQzoEkdO9FN0d9AA==", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.3.tgz", + "integrity": "sha512-BtQxwF27XUNnSafQLvDi0dQ8s3i6VgzSoQMJacpIcGNrlUdfHSKbgm3jmjCVvQluGzqwujQMPAoMai3oYSTurg==", "requires": { - "base64-arraybuffer": "~1.0.1" + "@socket.io/base64-arraybuffer": "~1.0.2" } }, "enquirer": { @@ -5234,7 +5249,7 @@ "qjobs": "^1.2.0", "range-parser": "^1.2.1", "rimraf": "^3.0.2", - "socket.io": "^4.2.0", + "socket.io": "^4.4.1", "source-map": "^0.6.1", "tmp": "^0.2.1", "ua-parser-js": "^0.7.30", @@ -6227,9 +6242,9 @@ "dev": true }, "negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" }, "neo-async": { "version": "2.6.2", @@ -9884,22 +9899,22 @@ } }, "socket.io": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.3.1.tgz", - "integrity": "sha512-HC5w5Olv2XZ0XJ4gOLGzzHEuOCfj3G0SmoW3jLHYYh34EVsIr3EkW9h6kgfW+K3TFEcmYy8JcPWe//KUkBp5jA==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.4.1.tgz", + "integrity": "sha512-s04vrBswdQBUmuWJuuNTmXUVJhP0cVky8bBDhdkf8y0Ptsu7fKU2LuLbts9g+pdmAdyMMn8F/9Mf1/wbtUN0fg==", "requires": { "accepts": "~1.3.4", "base64id": "~2.0.0", "debug": "~4.3.2", - "engine.io": "~6.0.0", - "socket.io-adapter": "~2.3.2", + "engine.io": "~6.1.0", + "socket.io-adapter": "~2.3.3", "socket.io-parser": "~4.0.4" }, "dependencies": { "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "requires": { "ms": "2.1.2" } @@ -9912,9 +9927,9 @@ } }, "socket.io-adapter": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.3.2.tgz", - "integrity": "sha512-PBZpxUPYjmoogY0aoaTmo1643JelsaS1CiAwNjRVdrI0X9Seuc19Y2Wife8k88avW6haG8cznvwbubAZwH4Mtg==" + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.3.3.tgz", + "integrity": "sha512-Qd/iwn3VskrpNO60BeRyCyr8ZWw9CPZyitW4AQwmRZ8zCiyDiL+znRnWX6tDHXnWn1sJrM1+b6Mn6wEDJJ4aYQ==" }, "socket.io-parser": { "version": "4.0.4", @@ -9932,9 +9947,9 @@ "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" }, "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "requires": { "ms": "2.1.2" } diff --git a/package.json b/package.json index 567b85901..e5ba090f1 100644 --- a/package.json +++ b/package.json @@ -71,8 +71,10 @@ "Jeff Jewiss ", "Jérémy Judéaux ", "Marcello Nuccio ", + "Nico Jansen ", "Pieter Mees ", "Sergei Startsev ", + "Tobias Speicher ", "pavelgj ", "sylvain-hamel ", "ywong ", @@ -108,7 +110,6 @@ "Levi Thomason ", "Luke Page ", "Matt Lewis ", - "Nico Jansen ", "Parashuram ", "Pat Tullmann ", "PatrickJS ", @@ -245,6 +246,7 @@ "Jon Bretman ", "Jonathan ES Lin ", "Jonathan Felchlin ", + "Jonathan Kingston ", "Jonathan Niles ", "Josh Lory ", "João Marcos Duarte ", @@ -424,10 +426,10 @@ "weiran.zsd@outlook.com>" ], "dependencies": { + "@colors/colors": "1.5.0", "body-parser": "^1.19.0", "braces": "^3.0.2", "chokidar": "^3.5.1", - "@colors/colors": "1.5.0", "connect": "^3.7.0", "di": "^0.0.1", "dom-serialize": "^2.2.1", @@ -443,7 +445,7 @@ "qjobs": "^1.2.0", "range-parser": "^1.2.1", "rimraf": "^3.0.2", - "socket.io": "^4.2.0", + "socket.io": "^4.4.1", "source-map": "^0.6.1", "tmp": "^0.2.1", "ua-parser-js": "^0.7.30", @@ -497,7 +499,7 @@ "engines": { "node": ">= 10" }, - "version": "6.3.17", + "version": "6.3.18", "license": "MIT", "scripts": { "lint": "eslint . --ext js --ignore-pattern *.tpl.js", diff --git a/static/context.js b/static/context.js index 8d697eff8..94e1f24ae 100644 --- a/static/context.js +++ b/static/context.js @@ -123,7 +123,7 @@ exports.isDefined = function (value) { exports.parseQueryParams = function (locationSearch) { var params = {} - var pairs = locationSearch.substr(1).split('&') + var pairs = locationSearch.slice(1).split('&') var keyValue for (var i = 0; i < pairs.length; i++) { diff --git a/static/karma.js b/static/karma.js index 23081eb7f..04c7ad322 100644 --- a/static/karma.js +++ b/static/karma.js @@ -348,7 +348,7 @@ var socket = io(location.host, { reconnectionDelay: 500, reconnectionDelayMax: Infinity, timeout: BROWSER_SOCKET_TIMEOUT, - path: KARMA_PROXY_PATH + KARMA_URL_ROOT.substr(1) + 'socket.io', + path: KARMA_PROXY_PATH + KARMA_URL_ROOT.slice(1) + 'socket.io', 'sync disconnect on unload': true, useNativeTimers: true }) @@ -565,7 +565,7 @@ exports.isDefined = function (value) { exports.parseQueryParams = function (locationSearch) { var params = {} - var pairs = locationSearch.substr(1).split('&') + var pairs = locationSearch.slice(1).split('&') var keyValue for (var i = 0; i < pairs.length; i++) {