Skip to content

Commit 206e5bf

Browse files
itaysabatotargos
authored andcommitted
worker: support relative paths
This commit adds support for relative paths in Worker. Paths are relative to the current working directory. PR-URL: #21407 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Guy Bedford <guybedford@gmail.com> Reviewed-By: Anatoli Papirovski <apapirovski@mac.com>
1 parent 8f1aa3c commit 206e5bf

File tree

7 files changed

+64
-20
lines changed

7 files changed

+64
-20
lines changed

doc/api/errors.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1754,10 +1754,11 @@ The fulfilled value of a linking promise is not a `vm.Module` object.
17541754
The current module's status does not allow for this operation. The specific
17551755
meaning of the error depends on the specific function.
17561756

1757-
<a id="ERR_WORKER_NEED_ABSOLUTE_PATH"></a>
1758-
### ERR_WORKER_NEED_ABSOLUTE_PATH
1757+
<a id="ERR_WORKER_PATH"></a>
1758+
### ERR_WORKER_PATH
17591759

1760-
The path for the main script of a worker is not an absolute path.
1760+
The path for the main script of a worker is neither an absolute path
1761+
nor a relative path starting with `./` or `../`.
17611762

17621763
<a id="ERR_WORKER_UNSERIALIZABLE_ERROR"></a>
17631764
### ERR_WORKER_UNSERIALIZABLE_ERROR

doc/api/worker_threads.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,9 @@ if (isMainThread) {
306306

307307
### new Worker(filename[, options])
308308

309-
* `filename` {string} The absolute path to the Worker’s main script.
309+
* `filename` {string} The path to the Worker’s main script. Must be
310+
either an absolute path or a relative path (i.e. relative to the
311+
current working directory) starting with `./` or `../`.
310312
If `options.eval` is true, this is a string containing JavaScript code rather
311313
than a path.
312314
* `options` {Object}

lib/internal/errors.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -854,8 +854,9 @@ E('ERR_VM_MODULE_NOT_LINKED',
854854
E('ERR_VM_MODULE_NOT_MODULE',
855855
'Provided module is not an instance of Module', Error);
856856
E('ERR_VM_MODULE_STATUS', 'Module status %s', Error);
857-
E('ERR_WORKER_NEED_ABSOLUTE_PATH',
858-
'The worker script filename must be an absolute path. Received "%s"',
857+
E('ERR_WORKER_PATH',
858+
'The worker script filename must be an absolute path or a relative ' +
859+
'path starting with \'./\' or \'../\'. Received "%s"',
859860
TypeError);
860861
E('ERR_WORKER_UNSERIALIZABLE_ERROR',
861862
'Serializing an uncaught exception failed', Error);

lib/internal/worker.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ const util = require('util');
77
const { Readable, Writable } = require('stream');
88
const {
99
ERR_INVALID_ARG_TYPE,
10-
ERR_WORKER_NEED_ABSOLUTE_PATH,
10+
ERR_WORKER_PATH,
1111
ERR_WORKER_UNSERIALIZABLE_ERROR,
1212
ERR_WORKER_UNSUPPORTED_EXTENSION,
1313
} = require('internal/errors').codes;
@@ -212,9 +212,15 @@ class Worker extends EventEmitter {
212212
}
213213

214214
if (!options.eval) {
215-
if (!path.isAbsolute(filename)) {
216-
throw new ERR_WORKER_NEED_ABSOLUTE_PATH(filename);
215+
if (!path.isAbsolute(filename) &&
216+
!filename.startsWith('./') &&
217+
!filename.startsWith('../') &&
218+
!filename.startsWith('.' + path.sep) &&
219+
!filename.startsWith('..' + path.sep)) {
220+
throw new ERR_WORKER_PATH(filename);
217221
}
222+
filename = path.resolve(filename);
223+
218224
const ext = path.extname(filename);
219225
if (ext !== '.js' && ext !== '.mjs') {
220226
throw new ERR_WORKER_UNSUPPORTED_EXTENSION(ext);
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Flags: --experimental-worker
2+
'use strict';
3+
const path = require('path');
4+
const assert = require('assert');
5+
const common = require('../common');
6+
const { Worker, isMainThread, parentPort } = require('worker_threads');
7+
8+
if (isMainThread) {
9+
const cwdName = path.relative('../', '.');
10+
const relativePath = path.relative('.', __filename);
11+
const w = new Worker(path.join('..', cwdName, relativePath));
12+
w.on('message', common.mustCall((message) => {
13+
assert.strictEqual(message, 'Hello, world!');
14+
}));
15+
} else {
16+
parentPort.postMessage('Hello, world!');
17+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Flags: --experimental-worker
2+
'use strict';
3+
const path = require('path');
4+
const assert = require('assert');
5+
const common = require('../common');
6+
const { Worker, isMainThread, parentPort } = require('worker_threads');
7+
8+
if (isMainThread) {
9+
const w = new Worker('./' + path.relative('.', __filename));
10+
w.on('message', common.mustCall((message) => {
11+
assert.strictEqual(message, 'Hello, world!');
12+
}));
13+
} else {
14+
parentPort.postMessage('Hello, world!');
15+
}
Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,11 @@
11
// Flags: --experimental-worker
22
'use strict';
33

4+
const path = require('path');
45
const common = require('../common');
56
const assert = require('assert');
67
const { Worker } = require('worker_threads');
78

8-
{
9-
const expectedErr = common.expectsError({
10-
code: 'ERR_WORKER_NEED_ABSOLUTE_PATH',
11-
type: TypeError
12-
}, 4);
13-
assert.throws(() => { new Worker('a.js'); }, expectedErr);
14-
assert.throws(() => { new Worker('b'); }, expectedErr);
15-
assert.throws(() => { new Worker('c/d.js'); }, expectedErr);
16-
assert.throws(() => { new Worker('a.mjs'); }, expectedErr);
17-
}
18-
199
{
2010
const expectedErr = common.expectsError({
2111
code: 'ERR_WORKER_UNSUPPORTED_EXTENSION',
@@ -25,3 +15,15 @@ const { Worker } = require('worker_threads');
2515
assert.throws(() => { new Worker('/c.wasm'); }, expectedErr);
2616
assert.throws(() => { new Worker('/d.txt'); }, expectedErr);
2717
}
18+
19+
{
20+
const expectedErr = common.expectsError({
21+
code: 'ERR_WORKER_PATH',
22+
type: TypeError
23+
}, 4);
24+
const existingRelPathNoDot = path.relative('.', __filename);
25+
assert.throws(() => { new Worker(existingRelPathNoDot); }, expectedErr);
26+
assert.throws(() => { new Worker('relative_no_dot'); }, expectedErr);
27+
assert.throws(() => { new Worker('file:///file_url'); }, expectedErr);
28+
assert.throws(() => { new Worker('https://www.url.com'); }, expectedErr);
29+
}

0 commit comments

Comments
 (0)