diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 1ad8cf50..96a4f361 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -19,16 +19,18 @@ jobs: - version: 10.x - version: 12.x - version: 14.x - - version: 15.x - mirror: https://nodejs.org/download/nightly - - version: 15.x - mirror: https://nodejs.org/download/v8-canary + # - version: 16.x + # - version: 18.x + # - version: 19.x + # mirror: https://nodejs.org/download/nightly + # - version: 19.x + # mirror: https://nodejs.org/download/v8-canary # os: [ubuntu-latest, macos-latest] # Temporarily disable MacOS until # https://github.com/nodejs/node/issues/32981 is fixed # TODO(mmarchini): test on 20.04 (need different lldb version) os: [ubuntu-18.04, ubuntu-20.04] - llvm: [ 8, 9 ] + llvm: [8, 9, 10, 11, 12, 13, 14] steps: - uses: actions/checkout@v1 - name: Use Node.js ${{ matrix.node.version }} ${{ matrix.node.mirror }} @@ -40,21 +42,55 @@ jobs: - name: install dependencies Linux if: startsWith(matrix.os, 'ubuntu-') run: | + use_llvm_repos=0 + + case "${{ matrix.os }}-${{ matrix.llvm }}" in + ubuntu-18.04-10) use_llvm_repos=1;; + ubuntu-18.04-11) use_llvm_repos=1;; + ubuntu-18.04-12) use_llvm_repos=1;; + ubuntu-18.04-13) use_llvm_repos=1;; + ubuntu-18.04-14) use_llvm_repos=1;; + ubuntu-20.04-13) use_llvm_repos=1;; + ubuntu-20.04-14) use_llvm_repos=1;; + *) use_llvm_repos=0;; + esac + + if [[ ${use_llvm_repos} == 1 ]]; then + wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -; + release="$(lsb_release -cs)" + cat << EOF | sudo tee /etc/apt/sources.list.d/llvm-${{ matrix.llvm }}.list + deb http://apt.llvm.org/${release}/ llvm-toolchain-${release}-${{ matrix.llvm }} main + deb-src http://apt.llvm.org/${release}/ llvm-toolchain-${release}-${{ matrix.llvm }} main + EOF + fi + sudo apt-get -qq update - sudo apt-get install lldb-${{ matrix.llvm }} liblldb-${{ matrix.llvm }}-dev lcov gdb -y - sudo ln -s $(which lldb-${{ matrix.llvm }}) /usr/bin/lldb + sudo apt-get install -y --no-install-recommends \ + lcov gdb \ + lldb-${{ matrix.llvm }} \ + liblldb-${{ matrix.llvm }}-dev + + if [[ -n "$(which lldb-${{ matrix.llvm }})" ]]; then + sudo ln -s "$(which lldb-${{ matrix.llvm }})" /usr/bin/lldb + sudo mkdir -p /usr/lib/lib/python3.8 + sudo ln -s /usr/lib/llvm-${{ matrix.llvm }}/lib/python3.8/site-packages /usr/lib/lib/python3.8/site-packages + fi + + if [[ -n "$(which llvm-config-${{ matrix.llvm }})" ]]; then + sudo ln -s "$(which llvm-config-${{ matrix.llvm }})" /usr/bin/llvm-config + fi - name: npm install run: | npm install --llnode_build_addon=true --llnode_coverage=true - name: run tests run: TEST_LLDB_BINARY=`which lldb-${{ matrix.llvm }}` npm run nyc-test-all - if: matrix.node.version != '15.x' + if: matrix.node.version != '19.x' - name: run tests (nightly) run: TEST_LLDB_BINARY=`which lldb-${{ matrix.llvm }}` npm run nyc-test-all - if: matrix.node.version == '15.x' + if: matrix.node.version == '19.x' continue-on-error: true - name: prepare coverage - if: startsWith(matrix.os, 'ubuntu-') && matrix.node.version != '15.x' + if: startsWith(matrix.os, 'ubuntu-') && matrix.node.version != '19.x' run: | npm run coverage cat ./coverage-js.info > ./coverage.info @@ -70,7 +106,7 @@ jobs: - name: Use Node.js LTS uses: actions/setup-node@v1 with: - node-version: 12.x + node-version: 18.x - name: npm install, build, and test run: | sudo apt-get -qq update diff --git a/scripts/linux.js b/scripts/linux.js index 40d0bbd0..d58fa468 100644 --- a/scripts/linux.js +++ b/scripts/linux.js @@ -21,10 +21,15 @@ function getLldbExecutable() { return process.env.npm_config_lldb_exe; } - const lldbExeNames = [ - 'lldb', 'lldb-5.0', 'lldb-4.0', - 'lldb-3.9', 'lldb-3.8', 'lldb-3.7', 'lldb-3.6' - ]; + // Use `Array.prototype.concat.apply` to support + // runtimes without `Array.prototype.flatMap`. + // Look for LLDB up to version 20. + const versions = Array.prototype.concat.apply([], + Array.from({length: 20}, (_, i) => i + 1).map((major) => + Array.from({ length: major < 4 ? 10 : 1 }, (_, minor) => major + '.' + minor) + )); + + const lldbExeNames = ['lldb'].concat(versions.reverse().map((v) => 'lldb-' + v)); return lldb.tryExecutables(lldbExeNames); } diff --git a/scripts/lldb.js b/scripts/lldb.js index 06226ad3..c0107eee 100644 --- a/scripts/lldb.js +++ b/scripts/lldb.js @@ -10,7 +10,23 @@ const fs = require('fs'); * @returns {string} Branch of the corresponding lldb release */ function versionToBranch(version) { - return 'release_' + version.replace('.', ''); + // `llvm-project` v1-3 branches are in the form `release/major.minor.x`: + // release/1.0.x ... release/3.9.x + // `llvm-project` v4-latest branches are in the form `release/major.x`: + // release/4.x ... release/12.x + + // split into array of semver components + var chars = (version.indexOf('.') === -1 + ? version.split('') // split `39` into ['3', '9'] + : version.split('.').filter(x => x !== '.') // split `3.9` into ['3', '9'] + ); + + // if version < 4, keep `major.minor` components + // if version >= 4, only keep `major` component + chars = chars.slice(0, (+chars[0] >= 4) ? 1 : 2); + + // join components into the form `release/3.9.x` + return 'release/' + chars.concat('x').join('.'); } /** @@ -44,18 +60,30 @@ function cloneHeaders(lldbVersion, buildDir) { if (!fs.existsSync(lldbInstallDir)) { console.log(`\nCloning lldb ${lldbHeadersBranch} into ${lldbInstallDir}`); + // use `git clone --filter` in git v2.19 to only download `lldb` dir of `llvm-project` monorepo + // see: https://stackoverflow.com/a/52269934/3117331 + // see: https://github.blog/2020-01-17-bring-your-monorepo-down-to-size-with-sparse-checkout/ child_process.execFileSync( 'git', ['clone', '--depth', '1', + '--filter=blob:none', + '--sparse', '--branch', lldbHeadersBranch, - 'https://github.com/llvm-mirror/lldb.git', + 'https://github.com/llvm/llvm-project.git', lldbInstallDir ], { stdio: 'inherit' }); // show progress + child_process.execFileSync( + 'git', [ + '-C', lldbInstallDir, + 'sparse-checkout', + 'set', 'lldb' + ], + { stdio: 'inherit' }); // show progress } else { console.log(`\nSkip cloning lldb headers because ${lldbInstallDir} exists`); } - return path.join(lldbInstallDir, 'include'); + return path.join(lldbInstallDir, 'lldb', 'include'); } /** diff --git a/test/common.js b/test/common.js index 14b890e9..a54abed6 100644 --- a/test/common.js +++ b/test/common.js @@ -42,7 +42,7 @@ function SessionOutput(session, stream, timeout) { this.waiting = false; this.waitQueue = []; let buf = ''; - this.timeout = timeout || 10000; + this.timeout = timeout || 20000; this.session = session; this.flush = function flush() { @@ -52,12 +52,23 @@ function SessionOutput(session, stream, timeout) { if (!this.waiting) break - let index = buf.indexOf('\n'); + let line = ''; + let index = 0; - if (index === -1) - break; + let inv = buf.indexOf('invalid_expr'); + if (inv !== -1) { + line = buf; + index = buf.length; + } else { + + index = buf.indexOf('\n'); + + if (index === -1) + break; + + line = buf.slice(0, index); + } - const line = buf.slice(0, index); buf = buf.slice(index + 1); if (/process \d+ exited/i.test(line)) @@ -107,6 +118,7 @@ SessionOutput.prototype.wait = function wait(regexp, callback, allLines) { const lines = []; function onLine(line) { + lines.push(line); if (self.session) debug(`[LINE][${self.session.lldb.pid}]`, line); @@ -158,7 +170,7 @@ SessionOutput.prototype.linesUntil = function linesUntil(regexp, callback) { function Session(options) { EventEmitter.call(this); - const timeout = parseInt(process.env.TEST_TIMEOUT) || 10000; + const timeout = parseInt(process.env.TEST_TIMEOUT) || 20000; const lldbBin = process.env.TEST_LLDB_BINARY || 'lldb'; const env = Object.assign({}, process.env); @@ -196,10 +208,6 @@ function Session(options) { this.stdout = new SessionOutput(this, this.lldb.stdout, timeout); this.stderr = new SessionOutput(this, this.lldb.stderr, timeout); - this.stderr.on('line', (line) => { - debug('[stderr]', line); - }); - // Map these methods to stdout for compatibility with legacy tests. this.wait = SessionOutput.prototype.wait.bind(this.stdout); this.waitError = SessionOutput.prototype.wait.bind(this.stderr); diff --git a/test/plugin/inspect-test.js b/test/plugin/inspect-test.js index 75510fa0..0ff8f795 100644 --- a/test/plugin/inspect-test.js +++ b/test/plugin/inspect-test.js @@ -658,11 +658,11 @@ function verifyInvalidExpr(t, sess) { return teardown(t, sess, err); } t.ok( - /error: error: use of undeclared identifier 'invalid_expr'/.test(line), + /use of undeclared identifier 'invalid_expr'/.test(line), 'invalid expression should return an error' ); teardown(t, sess); - }); + }, false); } tape('v8 inspect', (t) => { diff --git a/test/plugin/scan-test.js b/test/plugin/scan-test.js index 13b2cbd4..475c4a16 100644 --- a/test/plugin/scan-test.js +++ b/test/plugin/scan-test.js @@ -27,7 +27,7 @@ function testFindrefsForInvalidExpr(t, sess, next) { sess.waitError(/error:/, (err, line) => { t.error(err); t.ok( - /error: error: use of undeclared identifier 'invalid_expr'/.test(line), + /use of undeclared identifier 'invalid_expr'/.test(line), 'invalid expression should return an error' ); next(); diff --git a/test/plugin/workqueue-test.js b/test/plugin/workqueue-test.js index 7fcb7a93..5ffda231 100644 --- a/test/plugin/workqueue-test.js +++ b/test/plugin/workqueue-test.js @@ -26,7 +26,7 @@ function testWorkqueueCommands(t, sess) { } tape('v8 workqueue commands', (t) => { - t.timeoutAfter(15000); + t.timeoutAfter(30000); const sess = common.Session.create('workqueue-scenario.js'); sess.timeoutAfter