thread-stream 3.1.0 → 4.0.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.
@@ -1,12 +1,7 @@
1
1
  'use strict'
2
2
 
3
- const t = require('tap')
4
-
5
- if (process.env.CI) {
6
- t.skip('skip on CI')
7
- process.exit(0)
8
- }
9
-
3
+ const { test } = require('node:test')
4
+ const assert = require('node:assert')
10
5
  const { join } = require('path')
11
6
  const { file } = require('./helper')
12
7
  const { createReadStream } = require('fs')
@@ -15,27 +10,26 @@ const buffer = require('buffer')
15
10
 
16
11
  const MAX_STRING = buffer.constants.MAX_STRING_LENGTH
17
12
 
18
- t.plan(1)
19
-
20
- const dest = file()
21
- const stream = new ThreadStream({
22
- filename: join(__dirname, 'to-file.js'),
23
- workerData: { dest },
24
- sync: false
25
- })
26
-
27
- stream.on('close', async () => {
28
- t.comment('close emitted')
29
- let buf
30
- for await (const chunk of createReadStream(dest)) {
31
- buf = chunk
32
- }
33
- t.equal('asd', buf.toString().slice(-3))
34
- })
35
-
36
- stream.on('ready', () => {
37
- t.comment('open emitted')
38
- stream.write('a'.repeat(MAX_STRING - 2))
39
- stream.write('asd')
40
- stream.end()
13
+ test('string limit 2', { skip: process.env.CI }, (t, done) => {
14
+ const dest = file()
15
+ const stream = new ThreadStream({
16
+ filename: join(__dirname, 'to-file.js'),
17
+ workerData: { dest },
18
+ sync: false
19
+ })
20
+
21
+ stream.on('close', async () => {
22
+ let buf
23
+ for await (const chunk of createReadStream(dest)) {
24
+ buf = chunk
25
+ }
26
+ assert.strictEqual('asd', buf.toString().slice(-3))
27
+ done()
28
+ })
29
+
30
+ stream.on('ready', () => {
31
+ stream.write('a'.repeat(MAX_STRING - 2))
32
+ stream.write('asd')
33
+ stream.end()
34
+ })
41
35
  })
@@ -1,42 +1,37 @@
1
1
  'use strict'
2
2
 
3
- const t = require('tap')
4
-
5
- if (process.env.CI) {
6
- t.skip('skip on CI')
7
- process.exit(0)
8
- }
9
-
3
+ const { test } = require('node:test')
4
+ const assert = require('node:assert')
10
5
  const { join } = require('path')
11
6
  const { file } = require('./helper')
12
7
  const { stat } = require('fs')
13
8
  const ThreadStream = require('..')
14
9
 
15
- t.setTimeout(30000)
16
-
17
- const dest = file()
18
- const stream = new ThreadStream({
19
- filename: join(__dirname, 'to-file.js'),
20
- workerData: { dest },
21
- sync: false
22
- })
10
+ test('string limit', { skip: process.env.CI, timeout: 30000 }, (t, done) => {
11
+ const dest = file()
12
+ const stream = new ThreadStream({
13
+ filename: join(__dirname, 'to-file.js'),
14
+ workerData: { dest },
15
+ sync: false
16
+ })
23
17
 
24
- let length = 0
18
+ let length = 0
25
19
 
26
- stream.on('close', () => {
27
- stat(dest, (err, f) => {
28
- t.error(err)
29
- t.equal(f.size, length)
30
- t.end()
20
+ stream.on('close', () => {
21
+ stat(dest, (err, f) => {
22
+ assert.ifError(err)
23
+ assert.strictEqual(f.size, length)
24
+ done()
25
+ })
31
26
  })
32
- })
33
27
 
34
- const buf = Buffer.alloc(1024).fill('x').toString() // 1 KB
28
+ const buf = Buffer.alloc(1024).fill('x').toString() // 1 KB
35
29
 
36
- // This writes 1 GB of data
37
- for (let i = 0; i < 1024 * 1024; i++) {
38
- length += buf.length
39
- stream.write(buf)
40
- }
30
+ // This writes 1 GB of data
31
+ for (let i = 0; i < 1024 * 1024; i++) {
32
+ length += buf.length
33
+ stream.write(buf)
34
+ }
41
35
 
42
- stream.end()
36
+ stream.end()
37
+ })
@@ -1,6 +1,7 @@
1
1
  'use strict'
2
2
 
3
- const { test } = require('tap')
3
+ const { test } = require('node:test')
4
+ const assert = require('node:assert')
4
5
  const { fork } = require('child_process')
5
6
  const { join } = require('path')
6
7
  const { readFile } = require('fs').promises
@@ -13,10 +14,10 @@ test('exits with 0', async function (t) {
13
14
  const child = fork(join(__dirname, 'create-and-exit.js'), [dest])
14
15
 
15
16
  const [code] = await once(child, 'exit')
16
- t.equal(code, 0)
17
+ assert.strictEqual(code, 0)
17
18
 
18
19
  const data = await readFile(dest, 'utf8')
19
- t.equal(data, 'hello world\n')
20
+ assert.strictEqual(data, 'hello world\n')
20
21
  })
21
22
 
22
23
  test('emit error if thread exits', async function (t) {
@@ -25,20 +26,24 @@ test('emit error if thread exits', async function (t) {
25
26
  sync: true
26
27
  })
27
28
 
29
+ const closed = once(stream, 'close').catch(() => {})
30
+
28
31
  stream.on('ready', () => {
29
32
  stream.write('hello world\n')
30
33
  })
31
34
 
32
35
  let [err] = await once(stream, 'error')
33
- t.equal(err.message, 'the worker thread exited')
36
+ assert.strictEqual(err.message, 'the worker thread exited')
34
37
 
35
38
  stream.write('noop');
36
39
  [err] = await once(stream, 'error')
37
- t.equal(err.message, 'the worker has exited')
40
+ assert.strictEqual(err.message, 'the worker has exited')
38
41
 
39
42
  stream.write('noop');
40
43
  [err] = await once(stream, 'error')
41
- t.equal(err.message, 'the worker has exited')
44
+ assert.strictEqual(err.message, 'the worker has exited')
45
+
46
+ await closed
42
47
  })
43
48
 
44
49
  test('emit error if thread have unhandledRejection', async function (t) {
@@ -47,20 +52,24 @@ test('emit error if thread have unhandledRejection', async function (t) {
47
52
  sync: true
48
53
  })
49
54
 
55
+ const closed = once(stream, 'close').catch(() => {})
56
+
50
57
  stream.on('ready', () => {
51
58
  stream.write('hello world\n')
52
59
  })
53
60
 
54
61
  let [err] = await once(stream, 'error')
55
- t.equal(err.message, 'kaboom')
62
+ assert.strictEqual(err.message, 'kaboom')
56
63
 
57
64
  stream.write('noop');
58
65
  [err] = await once(stream, 'error')
59
- t.equal(err.message, 'the worker has exited')
66
+ assert.strictEqual(err.message, 'the worker has exited')
60
67
 
61
68
  stream.write('noop');
62
69
  [err] = await once(stream, 'error')
63
- t.equal(err.message, 'the worker has exited')
70
+ assert.strictEqual(err.message, 'the worker has exited')
71
+
72
+ await closed
64
73
  })
65
74
 
66
75
  test('emit error if worker stream emit error', async function (t) {
@@ -69,20 +78,24 @@ test('emit error if worker stream emit error', async function (t) {
69
78
  sync: true
70
79
  })
71
80
 
81
+ const closed = once(stream, 'close').catch(() => {})
82
+
72
83
  stream.on('ready', () => {
73
84
  stream.write('hello world\n')
74
85
  })
75
86
 
76
87
  let [err] = await once(stream, 'error')
77
- t.equal(err.message, 'kaboom')
88
+ assert.strictEqual(err.message, 'kaboom')
78
89
 
79
90
  stream.write('noop');
80
91
  [err] = await once(stream, 'error')
81
- t.equal(err.message, 'the worker has exited')
92
+ assert.strictEqual(err.message, 'the worker has exited')
82
93
 
83
94
  stream.write('noop');
84
95
  [err] = await once(stream, 'error')
85
- t.equal(err.message, 'the worker has exited')
96
+ assert.strictEqual(err.message, 'the worker has exited')
97
+
98
+ await closed
86
99
  })
87
100
 
88
101
  test('emit error if thread have uncaughtException', async function (t) {
@@ -91,20 +104,24 @@ test('emit error if thread have uncaughtException', async function (t) {
91
104
  sync: true
92
105
  })
93
106
 
107
+ const closed = once(stream, 'close').catch(() => {})
108
+
94
109
  stream.on('ready', () => {
95
110
  stream.write('hello world\n')
96
111
  })
97
112
 
98
113
  let [err] = await once(stream, 'error')
99
- t.equal(err.message, 'kaboom')
114
+ assert.strictEqual(err.message, 'kaboom')
100
115
 
101
116
  stream.write('noop');
102
117
  [err] = await once(stream, 'error')
103
- t.equal(err.message, 'the worker has exited')
118
+ assert.strictEqual(err.message, 'the worker has exited')
104
119
 
105
120
  stream.write('noop');
106
121
  [err] = await once(stream, 'error')
107
- t.equal(err.message, 'the worker has exited')
122
+ assert.strictEqual(err.message, 'the worker has exited')
123
+
124
+ await closed
108
125
  })
109
126
 
110
127
  test('close the work if out of scope on gc', { skip: !global.WeakRef }, async function (t) {
@@ -114,8 +131,8 @@ test('close the work if out of scope on gc', { skip: !global.WeakRef }, async fu
114
131
  })
115
132
 
116
133
  const [code] = await once(child, 'exit')
117
- t.equal(code, 0)
134
+ assert.strictEqual(code, 0)
118
135
 
119
136
  const data = await readFile(dest, 'utf8')
120
- t.equal(data, 'hello world\n')
137
+ assert.strictEqual(data, 'hello world\n')
121
138
  })
@@ -1,14 +1,13 @@
1
1
  'use strict'
2
2
 
3
- const { test } = require('tap')
3
+ const { test } = require('node:test')
4
+ const assert = require('node:assert')
4
5
  const { join } = require('path')
5
6
  const { file } = require('./helper')
6
7
  const ThreadStream = require('..')
7
8
 
8
9
  function basic (esVersion) {
9
- test(`transpiled-ts-to-${esVersion}`, function (t) {
10
- t.plan(2)
11
-
10
+ test(`transpiled-ts-to-${esVersion}`, function () {
12
11
  const dest = file()
13
12
  const stream = new ThreadStream({
14
13
  filename: join(__dirname, 'ts', `to-file.${esVersion}.cjs`),
@@ -18,9 +17,9 @@ function basic (esVersion) {
18
17
 
19
18
  // There are arbitrary checks, the important aspect of this test is to ensure
20
19
  // that we can properly load the transpiled file into our worker thread.
21
- t.same(stream.writableEnded, false)
20
+ assert.deepStrictEqual(stream.writableEnded, false)
22
21
  stream.end()
23
- t.same(stream.writableEnded, true)
22
+ assert.deepStrictEqual(stream.writableEnded, true)
24
23
  })
25
24
  }
26
25
 
@@ -0,0 +1,35 @@
1
+ import { test } from 'node:test'
2
+ import assert from 'node:assert'
3
+ import { readFile } from 'fs/promises'
4
+ import ThreadStream from '../index.js'
5
+ import { join } from 'desm'
6
+ import { file } from './helper.js'
7
+
8
+ const nodeVersion = parseInt(process.versions.node.split('.')[0], 10)
9
+
10
+ // Native TypeScript stripping (--experimental-strip-types) is only available in Node 22.6+
11
+ test('typescript module with native type stripping', { skip: nodeVersion < 22 }, async function (t) {
12
+ const dest = file()
13
+ const stream = new ThreadStream({
14
+ filename: join(import.meta.url, 'ts', 'to-file.ts'),
15
+ workerData: { dest },
16
+ workerOpts: {
17
+ execArgv: ['--experimental-strip-types', '--disable-warning=ExperimentalWarning']
18
+ },
19
+ sync: false
20
+ })
21
+
22
+ t.after(() => stream.end())
23
+
24
+ assert.ok(stream.write('hello world\n'))
25
+ assert.ok(stream.write('something else\n'))
26
+
27
+ stream.end()
28
+
29
+ await new Promise((resolve) => {
30
+ stream.on('close', resolve)
31
+ })
32
+
33
+ const data = await readFile(dest, 'utf8')
34
+ assert.strictEqual(data, 'hello world\nsomething else\n')
35
+ })
@@ -0,0 +1,35 @@
1
+ 'use strict'
2
+
3
+ const { test } = require('node:test')
4
+ const assert = require('node:assert')
5
+ const { readFile } = require('fs/promises')
6
+ const { join } = require('path')
7
+ const { file } = require('./helper')
8
+ const ThreadStream = require('..')
9
+
10
+ // This test verifies that TypeScript files can be loaded via ts-node
11
+ // when native type stripping is not enabled in the worker thread.
12
+ // Unlike ts.test.ts which passes --experimental-strip-types via execArgv,
13
+ // this test does NOT pass that flag, so the worker will fall back to ts-node.
14
+ test('typescript module with ts-node fallback', async function (t) {
15
+ const dest = file()
16
+ const stream = new ThreadStream({
17
+ filename: join(__dirname, 'ts', 'to-file.ts'),
18
+ workerData: { dest },
19
+ sync: false
20
+ })
21
+
22
+ t.after(() => stream.end())
23
+
24
+ assert.ok(stream.write('hello world\n'))
25
+ assert.ok(stream.write('something else\n'))
26
+
27
+ stream.end()
28
+
29
+ await new Promise((resolve) => {
30
+ stream.on('close', resolve)
31
+ })
32
+
33
+ const data = await readFile(dest, 'utf8')
34
+ assert.strictEqual(data, 'hello world\nsomething else\n')
35
+ })
package/.taprc DELETED
@@ -1,4 +0,0 @@
1
- jobs: 1
2
- check-coverage: false
3
- # in seconds
4
- timeout: 60
@@ -1,57 +0,0 @@
1
- const { test } = require('tap')
2
- const ThreadStream = require('../index')
3
- const { join } = require('path')
4
-
5
- function retryUntilTimeout (fn, timeout) {
6
- const start = Date.now()
7
- return new Promise((resolve, reject) => {
8
- async function run () {
9
- if (fn()) {
10
- resolve()
11
- return
12
- }
13
-
14
- if (Date.now() - start >= timeout) {
15
- reject(new Error('timeout'))
16
- return
17
- }
18
- setTimeout(run, 10)
19
- }
20
-
21
- run()
22
- })
23
- }
24
-
25
- const isNode18 = process.version.indexOf('v18') === 0
26
-
27
- test('emit warning when the worker gracefully exit without the stream ended', { skip: !isNode18 }, async function (t) {
28
- const expectedWarning = 'ThreadStream: process exited before destination stream was drained. this may indicate that the destination stream try to write to a another missing stream'
29
- const stream = new ThreadStream({
30
- filename: join(__dirname, 'to-next.js')
31
- })
32
- stream.unref()
33
-
34
- let streamWarning
35
- function saveWarning (e) {
36
- if (e.message === expectedWarning) {
37
- streamWarning = e
38
- }
39
- }
40
- process.on('warning', saveWarning)
41
-
42
- const data = 'hello'.repeat(10)
43
- for (let i = 0; i < 1000; i++) {
44
- if (streamWarning?.message === expectedWarning) {
45
- break
46
- }
47
- stream.write(data)
48
- await new Promise((resolve) => {
49
- setTimeout(resolve, 1)
50
- })
51
- }
52
-
53
- process.off('warning', saveWarning)
54
- t.equal(streamWarning?.message, expectedWarning)
55
-
56
- await retryUntilTimeout(() => stream.worker.exited === true, 3000)
57
- })
package/test/ts.test.ts DELETED
@@ -1,33 +0,0 @@
1
- import { test } from 'tap'
2
- import { readFile } from 'fs'
3
- import ThreadStream from '../index.js'
4
- import { join } from 'path'
5
- import { file } from './helper.js'
6
-
7
-
8
- test('typescript module', function (t) {
9
- t.plan(5)
10
-
11
- const dest = file()
12
- const stream = new ThreadStream({
13
- filename: join(__dirname, 'ts', 'to-file.ts'),
14
- workerData: { dest },
15
- sync: true
16
- })
17
-
18
- stream.on('finish', () => {
19
- readFile(dest, 'utf8', (err, data) => {
20
- t.error(err)
21
- t.equal(data, 'hello world\nsomething else\n')
22
- })
23
- })
24
-
25
- stream.on('close', () => {
26
- t.pass('close emitted')
27
- })
28
-
29
- t.ok(stream.write('hello world\n'))
30
- t.ok(stream.write('something else\n'))
31
-
32
- stream.end()
33
- })