From 11ff374ca3e7d06a3be4278b85ccee73392354e7 Mon Sep 17 00:00:00 2001 From: Mathias Bynens Date: Wed, 16 Oct 2019 17:00:20 +0200 Subject: [PATCH] chore: drop Node.js v6 support (#5045) Node.js v6 was end-of-life'd in April, 2019, with AWS Lambda prohibiting updaets to the Node.js v6 runtime since June 30, 2019. This makes it quite safe for us to remove the Node 6 support from the repository. --- .appveyor.yml | 8 +- .ci/node6/Dockerfile.linux | 17 -- .cirrus.yml | 9 - .travis.yml | 10 +- DeviceDescriptors.js | 13 +- Errors.js | 13 +- README.md | 5 +- .../puppeteer-firefox/DeviceDescriptors.js | 13 +- experimental/puppeteer-firefox/lib/Page.js | 3 +- experimental/puppeteer-firefox/lib/helper.js | 4 + .../misc/install-preferences.js | 4 +- index.js | 23 +-- install.js | 29 ---- lib/BrowserFetcher.js | 2 +- lib/Page.js | 1 + lib/helper.js | 4 + package.json | 8 +- test/evaluation.spec.js | 15 +- test/headful.spec.js | 7 +- test/launcher.spec.js | 7 +- utils/doclint/Source.js | 30 +--- .../TransformAsyncFunctions.js | 156 ------------------ utils/node6-transform/index.js | 64 ------- utils/node6-transform/test/test.js | 97 ----------- 24 files changed, 48 insertions(+), 494 deletions(-) delete mode 100644 .ci/node6/Dockerfile.linux delete mode 100644 utils/node6-transform/TransformAsyncFunctions.js delete mode 100644 utils/node6-transform/index.js delete mode 100644 utils/node6-transform/test/test.js diff --git a/.appveyor.yml b/.appveyor.yml index f69561b457df5..1ec90faa2b4da 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -1,8 +1,6 @@ environment: matrix: - - nodejs_version: "6.12.3" - FLAKINESS_DASHBOARD_NAME: Appveyor Chromium (Win + node6) - - nodejs_version: "8.11.3" + - nodejs_version: "8.16.0" FLAKINESS_DASHBOARD_NAME: Appveyor Chromium (Win + node8) FLAKINESS_DASHBOARD_PASSWORD: secure: g66jP+j6C+hkXLutBV9fdxB5fRJgcQQzy93SgQzXUmcCl/RjkJwnzyHvX0xfCVnv @@ -13,11 +11,9 @@ install: - ps: $env:FLAKINESS_DASHBOARD_BUILD_URL="https://ci.appveyor.com/project/aslushnikov/puppeteer/builds/$env:APPVEYOR_BUILD_ID/job/$env:APPVEYOR_JOB_ID" - ps: Install-Product node $env:nodejs_version - npm install - - if "%nodejs_version%" == "8.11.3" ( + - if "%nodejs_version%" == "8.16.0" ( npm run lint && npm run coverage && npm run test-doclint && npm run test-types - ) else ( - npm run unit-node6 ) diff --git a/.ci/node6/Dockerfile.linux b/.ci/node6/Dockerfile.linux deleted file mode 100644 index 77b416735d9db..0000000000000 --- a/.ci/node6/Dockerfile.linux +++ /dev/null @@ -1,17 +0,0 @@ -FROM node:6.12.3 - -RUN apt-get update && \ - apt-get -y install xvfb gconf-service libasound2 libatk1.0-0 libc6 libcairo2 libcups2 \ - libdbus-1-3 libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 \ - libgtk-3-0 libnspr4 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 \ - libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 \ - libxtst6 ca-certificates fonts-liberation libappindicator1 libnss3 lsb-release xdg-utils wget && \ - rm -rf /var/lib/apt/lists/* - -# Add user so we don't need --no-sandbox. -RUN groupadd -r pptruser && useradd -r -g pptruser -G audio,video pptruser \ - && mkdir -p /home/pptruser/Downloads \ - && chown -R pptruser:pptruser /home/pptruser - -# Run everything after as non-privileged user. -USER pptruser diff --git a/.cirrus.yml b/.cirrus.yml index d0d00b6167f08..6f47edb63a0c6 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -4,15 +4,6 @@ env: FLAKINESS_DASHBOARD_NAME: Cirrus ${CIRRUS_TASK_NAME} FLAKINESS_DASHBOARD_BUILD_URL: https://cirrus-ci.com/task/${CIRRUS_TASK_ID} -task: - matrix: - - name: Chromium (node6 + linux) - container: - dockerfile: .ci/node6/Dockerfile.linux - xvfb_start_background_script: Xvfb :99 -ac -screen 0 1024x768x24 - install_script: npm install --unsafe-perm - test_script: npm run unit-node6 - task: matrix: - name: Chromium (node8 + linux) diff --git a/.travis.yml b/.travis.yml index a6e3fd7645110..84f45ce3c4f3b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,24 +24,18 @@ script: - 'if [ "$NODE8" = "true" ]; then npm run test-types; fi' - 'if [ "$NODE8" = "true" ]; then npm run bundle; fi' - 'if [ "$NODE8" = "true" ]; then npm run unit-bundle; fi' - - 'if [ "$NODE6" = "true" ]; then npm run unit-node6; fi' jobs: include: - - node_js: "8.11.3" + - node_js: "8.16.0" env: - NODE8=true - FLAKINESS_DASHBOARD_NAME="Travis Chromium (node8 + linux)" - FLAKINESS_DASHBOARD_BUILD_URL="${TRAVIS_JOB_WEB_URL}" - - node_js: "8.11.3" + - node_js: "8.16.0" env: - FIREFOX=true - FLAKINESS_DASHBOARD_NAME="Travis Firefox (node8 + linux)" - FLAKINESS_DASHBOARD_BUILD_URL="${TRAVIS_JOB_WEB_URL}" - - node_js: "6.12.3" - env: - - NODE6=true - - FLAKINESS_DASHBOARD_NAME="Travis Chromium (node6 + linux)" - - FLAKINESS_DASHBOARD_BUILD_URL="${TRAVIS_JOB_WEB_URL}" before_deploy: "npm run apply-next-version" deploy: provider: npm diff --git a/DeviceDescriptors.js b/DeviceDescriptors.js index a89a09829000d..05135a115368c 100644 --- a/DeviceDescriptors.js +++ b/DeviceDescriptors.js @@ -14,15 +14,4 @@ * limitations under the License. */ -let asyncawait = true; -try { - new Function('async function test(){await 1}'); -} catch (error) { - asyncawait = false; -} - -// If node does not support async await, use the compiled version. -if (asyncawait) - module.exports = require('./lib/DeviceDescriptors'); -else - module.exports = require('./node6/lib/DeviceDescriptors'); +module.exports = require('./lib/DeviceDescriptors'); diff --git a/Errors.js b/Errors.js index dc41298ac12b2..4779e1d850812 100644 --- a/Errors.js +++ b/Errors.js @@ -14,15 +14,4 @@ * limitations under the License. */ -let asyncawait = true; -try { - new Function('async function test(){await 1}'); -} catch (error) { - asyncawait = false; -} - -// If node does not support async await, use the compiled version. -if (asyncawait) - module.exports = require('./lib/Errors'); -else - module.exports = require('./node6/lib/Errors'); +module.exports = require('./lib/Errors'); diff --git a/README.md b/README.md index 78c3cfc5b00ae..468eed34f5373 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,10 @@ See [puppeteer vs puppeteer-core](https://github.com/GoogleChrome/puppeteer/blob ### Usage -Note: Puppeteer requires at least Node v6.4.0, but the examples below use async/await which is only supported in Node v7.6.0 or greater. +Puppeteer follows the latest [maintenance LTS](https://github.com/nodejs/Release#release-schedule) version of Node. + +Note: Prior to v1.18.1, Puppeteer required at least Node v6.4.0. All subsequent versions rely on +Node 8.9.0+. All examples below use async/await which is only supported in Node v7.6.0 or greater. Puppeteer will be familiar to people using other browser testing frameworks. You create an instance of `Browser`, open pages, and then manipulate them with [Puppeteer's API](https://github.com/GoogleChrome/puppeteer/blob/v1.20.0/docs/api.md#). diff --git a/experimental/puppeteer-firefox/DeviceDescriptors.js b/experimental/puppeteer-firefox/DeviceDescriptors.js index a89a09829000d..05135a115368c 100644 --- a/experimental/puppeteer-firefox/DeviceDescriptors.js +++ b/experimental/puppeteer-firefox/DeviceDescriptors.js @@ -14,15 +14,4 @@ * limitations under the License. */ -let asyncawait = true; -try { - new Function('async function test(){await 1}'); -} catch (error) { - asyncawait = false; -} - -// If node does not support async await, use the compiled version. -if (asyncawait) - module.exports = require('./lib/DeviceDescriptors'); -else - module.exports = require('./node6/lib/DeviceDescriptors'); +module.exports = require('./lib/DeviceDescriptors'); diff --git a/experimental/puppeteer-firefox/lib/Page.js b/experimental/puppeteer-firefox/lib/Page.js index c2ce1bdb3ed6f..de5c7b41e95f1 100644 --- a/experimental/puppeteer-firefox/lib/Page.js +++ b/experimental/puppeteer-firefox/lib/Page.js @@ -4,7 +4,6 @@ const {Dialog} = require('./Dialog'); const {TimeoutError} = require('./Errors'); const fs = require('fs'); const mime = require('mime'); -const util = require('util'); const EventEmitter = require('events'); const {createHandle} = require('./JSHandle'); const {Events} = require('./Events'); @@ -15,7 +14,7 @@ const {TimeoutSettings} = require('./TimeoutSettings'); const {NavigationWatchdog} = require('./NavigationWatchdog'); const {Accessibility} = require('./Accessibility'); -const writeFileAsync = util.promisify(fs.writeFile); +const writeFileAsync = helper.promisify(fs.writeFile); class Page extends EventEmitter { /** diff --git a/experimental/puppeteer-firefox/lib/helper.js b/experimental/puppeteer-firefox/lib/helper.js index 1f417215c6a83..92e86ad22b5c6 100644 --- a/experimental/puppeteer-firefox/lib/helper.js +++ b/experimental/puppeteer-firefox/lib/helper.js @@ -65,6 +65,10 @@ class Helper { } } + /** + * @param {function} nodeFunction + * @return {function} + */ static promisify(nodeFunction) { function promisified(...args) { return new Promise((resolve, reject) => { diff --git a/experimental/puppeteer-firefox/misc/install-preferences.js b/experimental/puppeteer-firefox/misc/install-preferences.js index c536baa7eab6f..b48267091ddd6 100644 --- a/experimental/puppeteer-firefox/misc/install-preferences.js +++ b/experimental/puppeteer-firefox/misc/install-preferences.js @@ -1,14 +1,14 @@ const os = require('os'); const fs = require('fs'); const path = require('path'); +const util = require('util'); // Install browser preferences after downloading and unpacking // firefox instances. // Based on: https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Enterprise_deployment_before_60#Configuration async function installFirefoxPreferences(executablePath) { const firefoxFolder = path.dirname(executablePath); - const {helper} = require('../lib/helper'); - const mkdirAsync = helper.promisify(fs.mkdir.bind(fs)); + const mkdirAsync = util.promisify(fs.mkdir.bind(fs)); let prefPath = ''; let configPath = ''; diff --git a/index.js b/index.js index e7143fb3a5b18..a73d4d23d5fc6 100644 --- a/index.js +++ b/index.js @@ -14,25 +14,16 @@ * limitations under the License. */ -let asyncawait = true; -try { - new Function('async function test(){await 1}'); -} catch (error) { - asyncawait = false; -} - -if (asyncawait) { - const {helper} = require('./lib/helper'); - const api = require('./lib/api'); - for (const className in api) { - // Puppeteer-web excludes certain classes from bundle, e.g. BrowserFetcher. - if (typeof api[className] === 'function') - helper.installAsyncStackHooks(api[className]); - } +const {helper} = require('./lib/helper'); +const api = require('./lib/api'); +for (const className in api) { + // Puppeteer-web excludes certain classes from bundle, e.g. BrowserFetcher. + if (typeof api[className] === 'function') + helper.installAsyncStackHooks(api[className]); } // If node does not support async await, use the compiled version. -const Puppeteer = asyncawait ? require('./lib/Puppeteer') : require('./node6/lib/Puppeteer'); +const Puppeteer = require('./lib/Puppeteer'); const packageJson = require('./package.json'); const preferredRevision = packageJson.puppeteer.chromium_revision; const isPuppeteerCore = packageJson.name === 'puppeteer-core'; diff --git a/install.js b/install.js index d0e6c9181506a..1e9faf53ad0e2 100644 --- a/install.js +++ b/install.js @@ -18,8 +18,6 @@ if (require('./package.json').name === 'puppeteer-core') return; -buildNode6IfNecessary(); - if (process.env.PUPPETEER_SKIP_CHROMIUM_DOWNLOAD) { logPolitely('**INFO** Skipping Chromium download. "PUPPETEER_SKIP_CHROMIUM_DOWNLOAD" environment variable was found.'); return; @@ -109,34 +107,7 @@ function toMegabytes(bytes) { return `${Math.round(mb * 10) / 10} Mb`; } -function buildNode6IfNecessary() { - const fs = require('fs'); - const path = require('path'); - - // if this package is installed from NPM, then it already has up-to-date node6 - // folder. - if (!fs.existsSync(path.join('utils', 'node6-transform'))) - return; - // if async/await is supported, then node6 is not needed. - if (supportsAsyncAwait()) - return; - // Re-build node6/ folder. - logPolitely('Building Puppeteer for Node 6'); - require(path.join(__dirname, 'utils', 'node6-transform')); -} - -function supportsAsyncAwait() { - try { - new Function('async function test(){await 1}'); - } catch (error) { - return false; - } - return true; -} - function generateProtocolTypesIfNecessary(updated) { - if (!supportsAsyncAwait()) - return; const fs = require('fs'); const path = require('path'); if (!fs.existsSync(path.join(__dirname, 'utils', 'protocol-types-generator'))) diff --git a/lib/BrowserFetcher.js b/lib/BrowserFetcher.js index 4f0492bdcecac..aace9220591f4 100644 --- a/lib/BrowserFetcher.js +++ b/lib/BrowserFetcher.js @@ -17,8 +17,8 @@ const os = require('os'); const fs = require('fs'); const path = require('path'); -const extract = require('extract-zip'); const util = require('util'); +const extract = require('extract-zip'); const URL = require('url'); const {helper, assert} = require('./helper'); const removeRecursive = require('rimraf'); diff --git a/lib/Page.js b/lib/Page.js index 0ec70f53c56d7..0bdd217c8291f 100644 --- a/lib/Page.js +++ b/lib/Page.js @@ -31,6 +31,7 @@ const {Worker} = require('./Worker'); const {createJSHandle} = require('./JSHandle'); const {Accessibility} = require('./Accessibility'); const {TimeoutSettings} = require('./TimeoutSettings'); + const writeFileAsync = helper.promisify(fs.writeFile); class Page extends EventEmitter { diff --git a/lib/helper.js b/lib/helper.js index d6bd31439e222..3c5d987ad0b99 100644 --- a/lib/helper.js +++ b/lib/helper.js @@ -156,6 +156,10 @@ class Helper { return typeof obj === 'number' || obj instanceof Number; } + /** + * @param {function} nodeFunction + * @return {function} + */ static promisify(nodeFunction) { function promisified(...args) { return new Promise((resolve, reject) => { diff --git a/package.json b/package.json index cbd6d306e3505..66d31c2d89e44 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "index.js", "repository": "github:GoogleChrome/puppeteer", "engines": { - "node": ">=6.4.0" + "node": ">=8.16.0" }, "puppeteer": { "chromium_revision": "686378" @@ -15,14 +15,11 @@ "funit": "BROWSER=firefox node test/test.js", "debug-unit": "node --inspect-brk test/test.js", "test-doclint": "node utils/doclint/check_public_api/test/test.js && node utils/doclint/preprocessor/test.js", - "test": "npm run lint --silent && npm run coverage && npm run test-doclint && npm run test-node6-transformer && npm run test-types && node utils/testrunner/test/test.js", + "test": "npm run lint --silent && npm run coverage && npm run test-doclint && npm run test-types && node utils/testrunner/test/test.js", "install": "node install.js", "lint": "([ \"$CI\" = true ] && eslint --quiet -f codeframe . || eslint .) && npm run tsc && npm run doc", "doc": "node utils/doclint/cli.js", "coverage": "cross-env COVERAGE=true npm run unit", - "test-node6-transformer": "node utils/node6-transform/test/test.js", - "build": "node utils/node6-transform/index.js && node utils/doclint/generate_types", - "unit-node6": "node node6/test/test.js", "tsc": "tsc -p .", "prepublishOnly": "npm run build", "apply-next-version": "node utils/apply_next_version.js", @@ -63,7 +60,6 @@ }, "browser": { "./lib/BrowserFetcher.js": false, - "./node6/lib/Puppeteer": false, "ws": "./utils/browser/WebSocket", "fs": false, "child_process": false, diff --git a/test/evaluation.spec.js b/test/evaluation.spec.js index 3f68c8be32cb5..1bc670007910d 100644 --- a/test/evaluation.spec.js +++ b/test/evaluation.spec.js @@ -16,13 +16,6 @@ const utils = require('./utils'); -let asyncawait = true; -try { - new Function('async function foo() {await 1}'); -} catch (e) { - asyncawait = false; -} - const bigint = typeof BigInt !== 'undefined'; module.exports.addTests = function({testRunner, expect}) { @@ -74,14 +67,12 @@ module.exports.addTests = function({testRunner, expect}) { it_fails_ffox('should return undefined for objects with symbols', async({page, server}) => { expect(await page.evaluate(() => [Symbol('foo4')])).toBe(undefined); }); - (asyncawait ? it : xit)('should work with function shorthands', async({page, server}) => { - // trick node6 transpiler to not touch our object. - // TODO(lushnikov): remove eval once Node6 is dropped. - const a = eval(`({ + it('should work with function shorthands', async({page, server}) => { + const a = { sum(a, b) { return a + b; }, async mult(a, b) { return a * b; } - })`); + }; expect(await page.evaluate(a.sum, 1, 2)).toBe(3); expect(await page.evaluate(a.mult, 2, 4)).toBe(8); }); diff --git a/test/headful.spec.js b/test/headful.spec.js index a05cb309d7bef..80c7c4a52f6fb 100644 --- a/test/headful.spec.js +++ b/test/headful.spec.js @@ -17,11 +17,12 @@ const path = require('path'); const os = require('os'); const fs = require('fs'); -const {helper} = require('../lib/helper'); -const rmAsync = helper.promisify(require('rimraf')); +const util = require('util'); const utils = require('./utils'); const {waitEvent} = utils; -const mkdtempAsync = helper.promisify(fs.mkdtemp); + +const rmAsync = util.promisify(require('rimraf')); +const mkdtempAsync = util.promisify(fs.mkdtemp); const TMP_FOLDER = path.join(os.tmpdir(), 'pptr_tmp_folder-'); diff --git a/test/launcher.spec.js b/test/launcher.spec.js index b993eb2020d3c..8cb43a9737a42 100644 --- a/test/launcher.spec.js +++ b/test/launcher.spec.js @@ -233,9 +233,10 @@ module.exports.addTests = function({testRunner, expect, defaultBrowserOptions, p const browser = await puppeteer.launch(options); const pages = await browser.pages(); expect(pages.length).toBe(1); - if (pages[0].url() !== server.EMPTY_PAGE) - await pages[0].waitForNavigation(); - expect(pages[0].url()).toBe(server.EMPTY_PAGE); + const page = pages[0]; + if (page.url() !== server.EMPTY_PAGE) + await page.waitForNavigation(); + expect(page.url()).toBe(server.EMPTY_PAGE); await browser.close(); }); it('should set the default viewport', async() => { diff --git a/utils/doclint/Source.js b/utils/doclint/Source.js index 455f41924372e..dd77eac9469d3 100644 --- a/utils/doclint/Source.js +++ b/utils/doclint/Source.js @@ -15,11 +15,12 @@ */ const path = require('path'); +const util = require('util'); const fs = require('fs'); -const readFileAsync = promisify(fs.readFile); -const readdirAsync = promisify(fs.readdir); -const writeFileAsync = promisify(fs.writeFile); +const readFileAsync = util.promisify(fs.readFile); +const readdirAsync = util.promisify(fs.readdir); +const writeFileAsync = util.promisify(fs.writeFile); const PROJECT_DIR = path.join(__dirname, '..', '..'); @@ -110,26 +111,3 @@ class Source { } module.exports = Source; -/** - * @param {function(?)} nodeFunction - * @return {function(?):!Promise} - */ -function promisify(nodeFunction) { - /** - * @param {!Array} options - * @return {!Promise} - */ - return function(...options) { - return new Promise(function(fulfill, reject) { - options.push(callback); - nodeFunction.call(null, ...options); - function callback(err, result) { - if (err) - reject(err); - else - fulfill(result); - } - }); - }; -} - diff --git a/utils/node6-transform/TransformAsyncFunctions.js b/utils/node6-transform/TransformAsyncFunctions.js deleted file mode 100644 index 5903d89839d11..0000000000000 --- a/utils/node6-transform/TransformAsyncFunctions.js +++ /dev/null @@ -1,156 +0,0 @@ -/** - * Copyright 2017 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -const esprima = require('esprima'); -const ESTreeWalker = require('../ESTreeWalker'); - -// This is converted from Babel's "transform-async-to-generator" -// https://babeljs.io/docs/plugins/transform-async-to-generator/ -const asyncToGenerator = fn => { - const gen = fn.call(this); - return new Promise((resolve, reject) => { - function step(key, arg) { - let info, value; - try { - info = gen[key](arg); - value = info.value; - } catch (error) { - reject(error); - return; - } - if (info.done) { - resolve(value); - } else { - return Promise.resolve(value).then( - value => { - step('next', value); - }, - err => { - step('throw', err); - }); - } - } - return step('next'); - }); -}; - -/** - * @param {string} text - * @return {string} - */ -function transformAsyncFunctions(text) { - /** - * @type {!Array<{from: number, to: number, replacement: string}>} - */ - const edits = []; - - const ast = esprima.parseScript(text, {range: true, tolerant: true}); - const walker = new ESTreeWalker(node => { - if (node.type === 'FunctionExpression' || node.type === 'FunctionDeclaration' || node.type === 'ArrowFunctionExpression') - onBeforeFunction(node); - else if (node.type === 'AwaitExpression') - onBeforeAwait(node); - }, node => { - if (node.type === 'FunctionExpression' || node.type === 'FunctionDeclaration' || node.type === 'ArrowFunctionExpression') - onAfterFunction(node); - else if (node.type === 'AwaitExpression') - onAfterAwait(node); - }); - walker.walk(ast); - - edits.reverse(); - for (const {replacement, from, to} of edits) - text = text.substring(0, from) + replacement + text.substring(to); - - return text; - - /** - * @param {ESTree.Node} node - */ - function onBeforeFunction(node) { - if (!node.async) return; - - let range; - if (node.parent.type === 'MethodDefinition') - range = node.parent.range; - else - range = node.range; - const index = text.substring(range[0], range[1]).indexOf('async') + range[0]; - insertText(index, index + 'async'.length, '/* async */'); - - let before = `{return (${asyncToGenerator.toString()})(function*()`; - if (node.body.type !== 'BlockStatement') { - before += `{ return `; - - // Remove parentheses that might wrap an arrow function - const beforeBody = text.substring(node.range[0], node.body.range[0]); - if (/\(\s*$/.test(beforeBody)) { - const openParen = node.range[0] + beforeBody.lastIndexOf('('); - insertText(openParen, openParen + 1, ' '); - } - } - - - insertText(node.body.range[0], node.body.range[0], before); - } - - /** - * @param {ESTree.Node} node - */ - function onAfterFunction(node) { - if (!node.async) return; - - let after = `);}`; - if (node.body.type !== 'BlockStatement') - after = `; }` + after; - insertText(node.body.range[1], node.body.range[1], after); - - if (node.body.type !== 'BlockStatement') { - // Remove parentheses that might wrap an arrow function - const beforeBody = text.substring(node.range[0], node.body.range[0]); - if (/\(\s*$/.test(beforeBody)) { - const afterBody = text.substring(node.body.range[1], node.range[1]); - const closeParen = node.body.range[1] + afterBody.indexOf(')'); - insertText(closeParen, closeParen + 1, ' '); - } - } - } - - /** - * @param {ESTree.Node} node - */ - function onBeforeAwait(node) { - const index = text.substring(node.range[0], node.range[1]).indexOf('await') + node.range[0]; - insertText(index, index + 'await'.length, '(yield'); - } - - /** - * @param {ESTree.Node} node - */ - function onAfterAwait(node) { - insertText(node.range[1], node.range[1], ')'); - } - - /** - * @param {number} from - * @param {number} to - */ - function insertText(from, to, replacement) { - edits.push({from, to, replacement}); - } -} - -module.exports = transformAsyncFunctions; \ No newline at end of file diff --git a/utils/node6-transform/index.js b/utils/node6-transform/index.js deleted file mode 100644 index e96a79cf33443..0000000000000 --- a/utils/node6-transform/index.js +++ /dev/null @@ -1,64 +0,0 @@ -/** - * Copyright 2017 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -const fs = require('fs'); -const path = require('path'); -const removeRecursive = require('rimraf').sync; -const transformAsyncFunctions = require('./TransformAsyncFunctions'); - -const root = path.join(__dirname, '..', '..'); -const dest = path.join(__dirname, '..', '..', 'node6'); - -const excludes = [ - path.resolve(root, 'test', 'assets'), -]; - -if (fs.existsSync(dest)) - removeRecursive(dest); -fs.mkdirSync(dest); -fs.mkdirSync(path.join(dest, 'utils')); - -copyFolder(path.join(root, 'lib'), path.join(dest, 'lib')); -copyFolder(path.join(root, 'test'), path.join(dest, 'test')); -copyFolder(path.join(root, 'utils', 'testrunner'), path.join(dest, 'utils', 'testrunner')); -copyFolder(path.join(root, 'utils', 'testserver'), path.join(dest, 'utils', 'testserver')); -copyFolder(path.join(root, 'utils', 'flakiness-dashboard'), path.join(dest, 'utils', 'flakiness-dashboard')); - -function copyFolder(source, target) { - if (fs.existsSync(target)) - removeRecursive(target); - fs.mkdirSync(target); - - fs.readdirSync(source).forEach(file => { - const from = path.join(source, file); - const to = path.join(target, file); - if (fs.lstatSync(from).isDirectory()) - copyFolder(from, to); - else - copyFile(from, to); - }); -} - -function copyFile(from, to) { - let text = fs.readFileSync(from); - const isExcluded = excludes.some(exclude => from.startsWith(exclude)); - if (!isExcluded && from.endsWith('.js')) { - text = text.toString(); - const prefix = text.startsWith('#!') ? text.substring(0, text.indexOf('\n')) : ''; - text = prefix + transformAsyncFunctions(text.substring(prefix.length)); - } - fs.writeFileSync(to, text); -} diff --git a/utils/node6-transform/test/test.js b/utils/node6-transform/test/test.js deleted file mode 100644 index 46836d848ec8a..0000000000000 --- a/utils/node6-transform/test/test.js +++ /dev/null @@ -1,97 +0,0 @@ -/** - * Copyright 2017 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -const transformAsyncFunctions = require('../TransformAsyncFunctions'); - -const {TestRunner, Reporter, Matchers} = require('../../testrunner/'); -const runner = new TestRunner(); -new Reporter(runner); - -const {describe, xdescribe, fdescribe} = runner; -const {it, fit, xit} = runner; -const {beforeAll, beforeEach, afterAll, afterEach} = runner; - -const {expect} = new Matchers(); - -describe('TransformAsyncFunctions', function() { - it('should convert a function expression', function(done) { - const input = `(async function(){ return 123 })()`; - const output = eval(transformAsyncFunctions(input)); - expect(output instanceof Promise).toBe(true); - output.then(result => expect(result).toBe(123)).then(done); - }); - it('should convert an arrow function', function(done) { - const input = `(async () => 123)()`; - const output = eval(transformAsyncFunctions(input)); - expect(output instanceof Promise).toBe(true); - output.then(result => expect(result).toBe(123)).then(done); - }); - it('should convert an arrow function with curly braces', function(done) { - const input = `(async () => { return 123 })()`; - const output = eval(transformAsyncFunctions(input)); - expect(output instanceof Promise).toBe(true); - output.then(result => expect(result).toBe(123)).then(done); - }); - it('should convert a function declaration', function(done) { - const input = `async function f(){ return 123; } f();`; - const output = eval(transformAsyncFunctions(input)); - expect(output instanceof Promise).toBe(true); - output.then(result => expect(result).toBe(123)).then(done); - }); - it('should convert await', function(done) { - const input = `async function f(){ return 23 + await Promise.resolve(100); } f();`; - const output = eval(transformAsyncFunctions(input)); - expect(output instanceof Promise).toBe(true); - output.then(result => expect(result).toBe(123)).then(done); - }); - it('should convert method', function(done) { - const input = `class X{async f() { return 123 }} (new X()).f();`; - const output = eval(transformAsyncFunctions(input)); - expect(output instanceof Promise).toBe(true); - output.then(result => expect(result).toBe(123)).then(done); - }); - it('should pass arguments', function(done) { - const input = `(async function(a, b){ return await a + await b })(Promise.resolve(100), 23)`; - const output = eval(transformAsyncFunctions(input)); - expect(output instanceof Promise).toBe(true); - output.then(result => expect(result).toBe(123)).then(done); - }); - it('should still work across eval', function(done) { - const input = `var str = (async function(){ return 123; }).toString(); eval('(' + str + ')')();`; - const output = eval(transformAsyncFunctions(input)); - expect(output instanceof Promise).toBe(true); - output.then(result => expect(result).toBe(123)).then(done); - }); - it('should work with double await', function(done) { - const input = `async function f(){ return 23 + await Promise.resolve(50 + await Promise.resolve(50)); } f();`; - const output = eval(transformAsyncFunctions(input)); - expect(output instanceof Promise).toBe(true); - output.then(result => expect(result).toBe(123)).then(done); - }); - it('should work paren around arrow function', function(done) { - const input = `(async x => ( 123))()`; - const output = eval(transformAsyncFunctions(input)); - expect(output instanceof Promise).toBe(true); - output.then(result => expect(result).toBe(123)).then(done); - }); - it('should work async arrow with await', function(done) { - const input = `(async() => await 123)()`; - const output = eval(transformAsyncFunctions(input)); - expect(output instanceof Promise).toBe(true); - output.then(result => expect(result).toBe(123)).then(done); - }); -}); - -runner.run();