ava 3.11.0 → 3.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,121 @@
1
+ const v8 = require('v8');
2
+ const pkg = require('../../package.json');
3
+ const subprocess = require('./subprocess');
4
+ const options = require('./options');
5
+
6
+ const workers = new Map();
7
+ const workerTeardownFns = new WeakMap();
8
+
9
+ function createSharedWorker(filename, initialData, teardown) {
10
+ const channel = subprocess.registerSharedWorker(filename, initialData, teardown);
11
+
12
+ class ReceivedMessage {
13
+ constructor(id, serializedData) {
14
+ this.id = id;
15
+ this.data = v8.deserialize(new Uint8Array(serializedData));
16
+ }
17
+
18
+ reply(data) {
19
+ return publishMessage(data, this.id);
20
+ }
21
+ }
22
+
23
+ // Ensure that, no matter how often it's received, we have a stable message
24
+ // object.
25
+ const messageCache = new WeakMap();
26
+ async function * receiveMessages(replyTo) {
27
+ for await (const evt of channel.receive()) {
28
+ if (replyTo === undefined && evt.replyTo !== undefined) {
29
+ continue;
30
+ }
31
+
32
+ if (replyTo !== undefined && evt.replyTo !== replyTo) {
33
+ continue;
34
+ }
35
+
36
+ let message = messageCache.get(evt);
37
+ if (message === undefined) {
38
+ message = new ReceivedMessage(evt.messageId, evt.serializedData);
39
+ messageCache.set(evt, message);
40
+ }
41
+
42
+ yield message;
43
+ }
44
+ }
45
+
46
+ function publishMessage(data, replyTo) {
47
+ const id = channel.post([...v8.serialize(data)], replyTo);
48
+
49
+ return {
50
+ id,
51
+ async * replies() {
52
+ yield * receiveMessages(id);
53
+ }
54
+ };
55
+ }
56
+
57
+ return {
58
+ available: channel.available,
59
+ protocol: 'experimental',
60
+
61
+ get currentlyAvailable() {
62
+ return channel.currentlyAvailable;
63
+ },
64
+
65
+ publish(data) {
66
+ return publishMessage(data);
67
+ },
68
+
69
+ async * subscribe() {
70
+ yield * receiveMessages();
71
+ }
72
+ };
73
+ }
74
+
75
+ const supportsSharedWorkers = process.versions.node >= '12.17.0';
76
+
77
+ function registerSharedWorker({
78
+ filename,
79
+ initialData,
80
+ supportedProtocols,
81
+ teardown
82
+ }) {
83
+ if (!options.get().experiments.sharedWorkers) {
84
+ throw new Error('Shared workers are experimental. Opt in to them in your AVA configuration');
85
+ }
86
+
87
+ if (!supportsSharedWorkers) {
88
+ throw new Error('Shared workers require Node.js 12.17 or newer');
89
+ }
90
+
91
+ if (!supportedProtocols.includes('experimental')) {
92
+ throw new Error(`This version of AVA (${pkg.version}) does not support any of the desired shared worker protocols: ${supportedProtocols.join()}`);
93
+ }
94
+
95
+ let worker = workers.get(filename);
96
+ if (worker === undefined) {
97
+ worker = createSharedWorker(filename, initialData, async () => {
98
+ // Run possibly asynchronous teardown functions serially, in reverse
99
+ // order. Any error will crash the worker.
100
+ const teardownFns = workerTeardownFns.get(worker);
101
+ if (teardownFns !== undefined) {
102
+ for await (const fn of [...teardownFns].reverse()) {
103
+ await fn();
104
+ }
105
+ }
106
+ });
107
+ workers.set(filename, worker);
108
+ }
109
+
110
+ if (teardown !== undefined) {
111
+ if (workerTeardownFns.has(worker)) {
112
+ workerTeardownFns.get(worker).push(teardown);
113
+ } else {
114
+ workerTeardownFns.set(worker, [teardown]);
115
+ }
116
+ }
117
+
118
+ return worker;
119
+ }
120
+
121
+ exports.registerSharedWorker = registerSharedWorker;
@@ -32,6 +32,8 @@ ipc.options.then(async options => {
32
32
  const dependencyTracking = require('./dependency-tracker');
33
33
  const lineNumberSelection = require('./line-numbers');
34
34
 
35
+ const sharedWorkerTeardowns = [];
36
+
35
37
  async function exit(code) {
36
38
  if (!process.exitCode) {
37
39
  process.exitCode = code;
@@ -89,7 +91,7 @@ ipc.options.then(async options => {
89
91
  exit(1);
90
92
  });
91
93
 
92
- runner.on('finish', () => {
94
+ runner.on('finish', async () => {
93
95
  try {
94
96
  const {cannotSave, touchedFiles} = runner.saveSnapshotState();
95
97
  if (cannotSave) {
@@ -103,6 +105,14 @@ ipc.options.then(async options => {
103
105
  return;
104
106
  }
105
107
 
108
+ try {
109
+ await Promise.all(sharedWorkerTeardowns.map(fn => fn()));
110
+ } catch (error) {
111
+ ipc.send({type: 'uncaught-exception', err: serializeError('Shared worker teardown error', false, error, runner.file)});
112
+ exit(1);
113
+ return;
114
+ }
115
+
106
116
  nowAndTimers.setImmediate(() => {
107
117
  currentlyUnhandled()
108
118
  .filter(rejection => !attributedRejections.has(rejection.promise))
@@ -129,6 +139,19 @@ ipc.options.then(async options => {
129
139
  return runner;
130
140
  };
131
141
 
142
+ exports.registerSharedWorker = (filename, initialData, teardown) => {
143
+ const {channel, forceUnref, ready} = ipc.registerSharedWorker(filename, initialData);
144
+ runner.waitForReady.push(ready);
145
+ sharedWorkerTeardowns.push(async () => {
146
+ try {
147
+ await teardown();
148
+ } finally {
149
+ forceUnref();
150
+ }
151
+ });
152
+ return channel;
153
+ };
154
+
132
155
  // Store value to prevent required modules from modifying it.
133
156
  const testPath = options.file;
134
157
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ava",
3
- "version": "3.11.0",
3
+ "version": "3.13.0",
4
4
  "description": "Node.js test runner that lets you develop with confidence.",
5
5
  "license": "MIT",
6
6
  "repository": "avajs/ava",
@@ -16,7 +16,8 @@
16
16
  "lib",
17
17
  "*.js",
18
18
  "!*.config.js",
19
- "index.d.ts"
19
+ "index.d.ts",
20
+ "*.d.ts"
20
21
  ],
21
22
  "keywords": [
22
23
  "🦄",
@@ -56,14 +57,14 @@
56
57
  ],
57
58
  "dependencies": {
58
59
  "@concordance/react": "^2.0.0",
59
- "acorn": "^7.3.1",
60
- "acorn-walk": "^7.2.0",
60
+ "acorn": "^8.0.1",
61
+ "acorn-walk": "^8.0.0",
61
62
  "ansi-styles": "^4.2.1",
62
63
  "arrgv": "^1.0.2",
63
64
  "arrify": "^2.0.1",
64
65
  "callsites": "^3.1.0",
65
66
  "chalk": "^4.1.0",
66
- "chokidar": "^3.4.1",
67
+ "chokidar": "^3.4.2",
67
68
  "chunkd": "^2.0.1",
68
69
  "ci-info": "^2.0.0",
69
70
  "ci-parallel-vars": "^1.0.1",
@@ -72,11 +73,11 @@
72
73
  "cli-truncate": "^2.1.0",
73
74
  "code-excerpt": "^3.0.0",
74
75
  "common-path-prefix": "^3.0.0",
75
- "concordance": "^5.0.0",
76
+ "concordance": "^5.0.1",
76
77
  "convert-source-map": "^1.7.0",
77
78
  "currently-unhandled": "^0.4.1",
78
- "debug": "^4.1.1",
79
- "del": "^5.1.0",
79
+ "debug": "^4.2.0",
80
+ "del": "^6.0.0",
80
81
  "emittery": "^0.7.1",
81
82
  "equal-length": "^1.0.0",
82
83
  "figures": "^3.2.0",
@@ -85,19 +86,20 @@
85
86
  "import-local": "^3.0.2",
86
87
  "indent-string": "^4.0.0",
87
88
  "is-error": "^2.2.2",
88
- "is-plain-object": "^4.1.1",
89
+ "is-plain-object": "^5.0.0",
89
90
  "is-promise": "^4.0.0",
90
- "lodash": "^4.17.19",
91
+ "lodash": "^4.17.20",
91
92
  "matcher": "^3.0.0",
92
93
  "md5-hex": "^3.0.1",
93
- "mem": "^6.1.0",
94
+ "mem": "^6.1.1",
94
95
  "ms": "^2.1.2",
95
- "ora": "^4.0.5",
96
+ "ora": "^5.1.0",
97
+ "p-event": "^4.2.0",
96
98
  "p-map": "^4.0.0",
97
99
  "picomatch": "^2.2.2",
98
100
  "pkg-conf": "^3.1.0",
99
101
  "plur": "^4.0.0",
100
- "pretty-ms": "^7.0.0",
102
+ "pretty-ms": "^7.0.1",
101
103
  "read-pkg": "^5.2.0",
102
104
  "resolve-cwd": "^3.0.0",
103
105
  "slash": "^3.0.0",
@@ -107,9 +109,9 @@
107
109
  "supertap": "^1.0.0",
108
110
  "temp-dir": "^2.0.0",
109
111
  "trim-off-newlines": "^1.0.1",
110
- "update-notifier": "^4.1.0",
112
+ "update-notifier": "^4.1.1",
111
113
  "write-file-atomic": "^3.0.3",
112
- "yargs": "^15.4.1"
114
+ "yargs": "^16.0.3"
113
115
  },
114
116
  "devDependencies": {
115
117
  "@ava/babel": "^1.0.1",
@@ -117,25 +119,25 @@
117
119
  "@babel/plugin-proposal-do-expressions": "^7.10.4",
118
120
  "@sinonjs/fake-timers": "^6.0.1",
119
121
  "ansi-escapes": "^4.3.1",
120
- "c8": "^7.2.1",
122
+ "c8": "^7.3.1",
121
123
  "delay": "^4.4.0",
122
124
  "esm": "^3.2.25",
123
125
  "execa": "^4.0.3",
124
- "get-stream": "^5.1.0",
125
- "p-event": "^4.2.0",
126
+ "get-stream": "^6.0.0",
127
+ "it-first": "^1.0.4",
126
128
  "proxyquire": "^2.1.3",
127
129
  "react": "^16.13.1",
128
130
  "react-test-renderer": "^16.13.1",
129
131
  "replace-string": "^3.1.0",
130
- "sinon": "^9.0.2",
132
+ "sinon": "^9.0.3",
131
133
  "source-map-fixtures": "^2.1.0",
132
134
  "tap": "^14.10.8",
133
135
  "temp-write": "^4.0.0",
134
- "tempy": "^0.6.0",
136
+ "tempy": "^0.7.1",
135
137
  "touch": "^3.1.0",
136
138
  "tsd": "^0.13.1",
137
- "typescript": "^3.9.7",
138
- "xo": "^0.32.1",
139
+ "typescript": "^4.0.3",
140
+ "xo": "^0.33.1",
139
141
  "zen-observable": "^0.8.15"
140
142
  }
141
143
  }
package/plugin.d.ts ADDED
@@ -0,0 +1,81 @@
1
+ export namespace SharedWorker {
2
+ export type ProtocolIdentifier = 'experimental';
3
+
4
+ /* eslint-disable @typescript-eslint/method-signature-style */
5
+ export type FactoryOptions = {
6
+ negotiateProtocol <Data = unknown>(supported: readonly ['experimental']): Experimental.Protocol<Data>;
7
+ // Add overloads for additional protocols.
8
+ };
9
+ /* eslint-enable @typescript-eslint/method-signature-style */
10
+
11
+ export type Factory = (options: FactoryOptions) => void;
12
+
13
+ export namespace Experimental {
14
+ export type Protocol<Data = unknown> = {
15
+ readonly initialData: Data;
16
+ readonly protocol: 'experimental';
17
+ broadcast: (data: Data) => BroadcastMessage<Data>;
18
+ ready: () => Protocol<Data>;
19
+ subscribe: () => AsyncIterableIterator<ReceivedMessage<Data>>;
20
+ testWorkers: () => AsyncIterableIterator<TestWorker<Data>>;
21
+ };
22
+
23
+ export type BroadcastMessage<Data = unknown> = {
24
+ readonly id: string;
25
+ replies: () => AsyncIterableIterator<ReceivedMessage<Data>>;
26
+ };
27
+
28
+ export type PublishedMessage<Data = unknown> = {
29
+ readonly id: string;
30
+ replies: () => AsyncIterableIterator<ReceivedMessage<Data>>;
31
+ };
32
+
33
+ export type ReceivedMessage<Data = unknown> = {
34
+ readonly data: Data;
35
+ readonly id: string;
36
+ readonly testWorker: TestWorker;
37
+ reply: (data: Data) => PublishedMessage<Data>;
38
+ };
39
+
40
+ export type TestWorker<Data = unknown> = {
41
+ readonly id: string;
42
+ readonly file: string;
43
+ publish: (data: Data) => PublishedMessage<Data>;
44
+ subscribe: () => AsyncIterableIterator<ReceivedMessage<Data>>;
45
+ teardown: <TeardownFn extends () => void> (fn: TeardownFn) => TeardownFn;
46
+ };
47
+ }
48
+
49
+ export namespace Plugin {
50
+ export type RegistrationOptions<Identifier extends ProtocolIdentifier, Data = unknown> = {
51
+ readonly filename: string;
52
+ readonly initialData?: Data;
53
+ readonly supportedProtocols: readonly Identifier[];
54
+ readonly teardown?: () => void;
55
+ };
56
+
57
+ export namespace Experimental {
58
+ export type Protocol<Data = unknown> = {
59
+ readonly available: Promise<void>;
60
+ readonly currentlyAvailable: boolean;
61
+ readonly protocol: 'experimental';
62
+ publish: (data: Data) => PublishedMessage<Data>;
63
+ subscribe: () => AsyncIterableIterator<ReceivedMessage<Data>>;
64
+ };
65
+
66
+ export type PublishedMessage<Data = unknown> = {
67
+ readonly id: string;
68
+ replies: () => AsyncIterableIterator<ReceivedMessage<Data>>;
69
+ };
70
+
71
+ export type ReceivedMessage<Data = unknown> = {
72
+ readonly data: Data;
73
+ readonly id: string;
74
+ reply: (data: Data) => PublishedMessage<Data>;
75
+ };
76
+ }
77
+ }
78
+ }
79
+
80
+ export function registerSharedWorker<Data = unknown>(options: SharedWorker.Plugin.RegistrationOptions<'experimental', Data>): SharedWorker.Plugin.Experimental.Protocol<Data>;
81
+ // Add overloads for additional protocols.
package/plugin.js ADDED
@@ -0,0 +1,9 @@
1
+ 'use strict';
2
+ const path = require('path');
3
+
4
+ // Ensure the same AVA install is loaded by the test file as by the test worker
5
+ if (process.env.AVA_PATH && process.env.AVA_PATH !== __dirname) {
6
+ module.exports = require(path.join(process.env.AVA_PATH, 'plugin'));
7
+ } else {
8
+ module.exports = require('./lib/worker/plugin');
9
+ }
package/readme.md CHANGED
@@ -211,9 +211,9 @@ It's the [Andromeda galaxy](https://simple.wikipedia.org/wiki/Andromeda_galaxy).
211
211
 
212
212
  ## Team
213
213
 
214
- [![Mark Wubben](https://github.com/novemberborn.png?size=100)](https://github.com/novemberborn) | [![Sindre Sorhus](https://github.com/sindresorhus.png?size=100)](https://github.com/sindresorhus) | [![Vadim Demedes](https://github.com/vadimdemedes.png?size=100)](https://github.com/vadimdemedes)
215
- ---|---|---
216
- [Mark Wubben](https://novemberborn.net) | [Sindre Sorhus](https://sindresorhus.com) | [Vadim Demedes](https://github.com/vadimdemedes)
214
+ [![Mark Wubben](https://github.com/novemberborn.png?size=100)](https://github.com/novemberborn) | [![Sindre Sorhus](https://github.com/sindresorhus.png?size=100)](https://github.com/sindresorhus)
215
+ ---|---
216
+ [Mark Wubben](https://novemberborn.net) | [Sindre Sorhus](https://sindresorhus.com)
217
217
 
218
218
  ###### Former
219
219
 
@@ -221,6 +221,7 @@ It's the [Andromeda galaxy](https://simple.wikipedia.org/wiki/Andromeda_galaxy).
221
221
  - [James Talmage](https://github.com/jamestalmage)
222
222
  - [Juan Soto](https://github.com/sotojuan)
223
223
  - [Jeroen Engels](https://github.com/jfmengels)
224
+ - [Vadim Demedes](https://github.com/vadimdemedes)
224
225
 
225
226
 
226
227
  <div align="center">
@@ -1,13 +0,0 @@
1
- 'use strict';
2
- function whileCorked(stream, fn) {
3
- return function (...args) {
4
- stream.cork();
5
- try {
6
- fn.apply(this, args);
7
- } finally {
8
- stream.uncork();
9
- }
10
- };
11
- }
12
-
13
- module.exports = whileCorked;