From 7f13b49e57adbd1a9821ae33bb5912b6474df092 Mon Sep 17 00:00:00 2001 From: Domenic Denicola Date: Thu, 11 Oct 2018 15:02:02 -0400 Subject: [PATCH] Meta: fix realm issues in reference implementation testing setup By bundling together the reference implementation using browserify, then evaluating it inside the wpt-runner window context, we fix all the cross-realm issues that have plagued us. This includes promise assimilation (which we had a workaround in place for), as well as Object.prototype identity (came up when testing async iterators) and the presence of DOMException and AbortSignal on the global (came up when testing #744). --- reference-implementation/.eslintrc.json | 6 +- reference-implementation/lib/index.js | 16 ++++ reference-implementation/package.json | 7 +- .../run-web-platform-tests.js | 79 ++++++++++--------- 4 files changed, 64 insertions(+), 44 deletions(-) create mode 100644 reference-implementation/lib/index.js diff --git a/reference-implementation/.eslintrc.json b/reference-implementation/.eslintrc.json index 42f6adb83..c09c1518a 100644 --- a/reference-implementation/.eslintrc.json +++ b/reference-implementation/.eslintrc.json @@ -2,10 +2,11 @@ "root": true, "env": { "node": true, + "browser": true, "es6": true }, "parserOptions": { - "ecmaVersion": 6 + "ecmaVersion": 2018 }, "globals": { "ReadableStream": false, @@ -13,7 +14,8 @@ "TransformStream": false, "ByteLengthQueuingStrategy": false, "CountQueuingStrategy": false, - "GCController": false + "GCController": false, + "gc": false }, "rules": { // Possible errors diff --git a/reference-implementation/lib/index.js b/reference-implementation/lib/index.js new file mode 100644 index 000000000..d42621689 --- /dev/null +++ b/reference-implementation/lib/index.js @@ -0,0 +1,16 @@ +'use strict'; +// This file is used as the entry point for browserifying the reference implementation to allow it +// to run inside the wpt-runner "browser like" context. + +const { ReadableStream } = require('./readable-stream.js'); +const { WritableStream } = require('./writable-stream.js'); +const { TransformStream } = require('./transform-stream.js'); +const ByteLengthQueuingStrategy = require('./byte-length-queuing-strategy.js'); +const CountQueuingStrategy = require('./count-queuing-strategy.js'); + +window.ReadableStream = ReadableStream; +window.WritableStream = WritableStream; +window.TransformStream = TransformStream; +window.ByteLengthQueuingStrategy = ByteLengthQueuingStrategy; +window.CountQueuingStrategy = CountQueuingStrategy; +window.gc = gc; diff --git a/reference-implementation/package.json b/reference-implementation/package.json index 722ae4410..29d495f65 100644 --- a/reference-implementation/package.json +++ b/reference-implementation/package.json @@ -12,11 +12,12 @@ "license": "(CC0-1.0 OR MIT)", "devDependencies": { "better-assert": "^1.0.2", - "debug": "^3.1.0", + "browserify": "^16.2.3", + "debug": "^4.1.0", "eslint": "^3.2.2", "minimatch": "^3.0.4", - "nyc": "^11.2.1", - "opener": "^1.4.2", + "nyc": "^13.0.1", + "opener": "^1.5.1", "wpt-runner": "^2.2.0" }, "nyc": { diff --git a/reference-implementation/run-web-platform-tests.js b/reference-implementation/run-web-platform-tests.js index 5bc2b3dde..fcf7cf6d0 100644 --- a/reference-implementation/run-web-platform-tests.js +++ b/reference-implementation/run-web-platform-tests.js @@ -1,26 +1,13 @@ // This runs the web platform tests against the reference implementation, in Node.js using jsdom, for easier rapid // development of the reference implementation and the web platform tests. -/* eslint-disable no-console*/ +/* eslint-disable no-console */ 'use strict'; const path = require('path'); +const { promisify } = require('util'); +const browserify = require('browserify'); const wptRunner = require('wpt-runner'); const minimatch = require('minimatch'); -const { ReadableStream } = require('./lib/readable-stream.js'); -const { WritableStream } = require('./lib/writable-stream.js'); -const { TransformStream } = require('./lib/transform-stream.js'); -const ByteLengthQueuingStrategy = require('./lib/byte-length-queuing-strategy.js'); -const CountQueuingStrategy = require('./lib/count-queuing-strategy.js'); - -const testsPath = path.resolve(__dirname, 'web-platform-tests/streams'); - -const filterGlobs = process.argv.length >= 3 ? process.argv.slice(2) : ['**/*.html']; -const workerTestPattern = /\.(?:dedicated|shared|service)worker(?:\.https)?\.html$/; -function filter(testPath) { - return !workerTestPattern.test(testPath) && // ignore the worker versions - filterGlobs.some(glob => minimatch(testPath, glob)); -} - // wpt-runner does not yet support unhandled rejection tracking a la // https://github.com/w3c/testharness.js/commit/7716e2581a86dfd9405a9c00547a7504f0c7fe94 // So we emulate it with Node.js events @@ -33,32 +20,46 @@ process.on('rejectionHandled', promise => { rejections.delete(promise); }); -wptRunner(testsPath, { rootURL: 'streams/', setup, filter }) - .then(failures => { - process.exitCode = failures; +main().catch(e => { + console.error(e.stack); + process.exitCode = 1; +}); + +async function main() { + const entryPath = path.resolve(__dirname, 'lib/index.js'); + const testsPath = path.resolve(__dirname, 'web-platform-tests/streams'); + + const filterGlobs = process.argv.length >= 3 ? process.argv.slice(2) : ['**/*.html']; + const workerTestPattern = /\.(?:dedicated|shared|service)worker(?:\.https)?\.html$/; + + const bundledJS = await bundle(entryPath); - if (rejections.size > 0) { - if (failures === 0) { - process.exitCode = 1; - } + const failures = await wptRunner(testsPath, { + rootURL: 'streams/', + setup(window) { + window.eval(bundledJS); + }, + filter(testPath) { + return !workerTestPattern.test(testPath) && // ignore the worker versions + filterGlobs.some(glob => minimatch(testPath, glob)); + } + }); - for (const reason of rejections.values()) { - console.error('Unhandled promise rejection: ', reason.stack); - } - } - }) - .catch(e => { - console.error(e.stack); + process.exitCode = failures; + + if (rejections.size > 0) { + if (failures === 0) { process.exitCode = 1; - }); + } -function setup(window) { - // Necessary so that we can send test-realm promises to the jsdom-realm implementation without causing assimilation. - window.Promise = Promise; + for (const reason of rejections.values()) { + console.error('Unhandled promise rejection: ', reason.stack); + } + } +} - window.ReadableStream = ReadableStream; - window.WritableStream = WritableStream; - window.TransformStream = TransformStream; - window.ByteLengthQueuingStrategy = ByteLengthQueuingStrategy; - window.CountQueuingStrategy = CountQueuingStrategy; +async function bundle(entryPath) { + const b = browserify([entryPath]); + const buffer = await promisify(b.bundle.bind(b))(); + return buffer.toString(); }