Skip to content

Commit

Permalink
worker: support relative paths
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
itaysabato authored and targos committed Jun 28, 2018
1 parent 8f1aa3c commit 206e5bf
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 20 deletions.
7 changes: 4 additions & 3 deletions doc/api/errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -1754,10 +1754,11 @@ The fulfilled value of a linking promise is not a `vm.Module` object.
The current module's status does not allow for this operation. The specific
meaning of the error depends on the specific function.

<a id="ERR_WORKER_NEED_ABSOLUTE_PATH"></a>
### ERR_WORKER_NEED_ABSOLUTE_PATH
<a id="ERR_WORKER_PATH"></a>
### ERR_WORKER_PATH

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

<a id="ERR_WORKER_UNSERIALIZABLE_ERROR"></a>
### ERR_WORKER_UNSERIALIZABLE_ERROR
Expand Down
4 changes: 3 additions & 1 deletion doc/api/worker_threads.md
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,9 @@ if (isMainThread) {

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

* `filename` {string} The absolute path to the Worker’s main script.
* `filename` {string} The path to the Worker’s main script. Must be
either an absolute path or a relative path (i.e. relative to the
current working directory) starting with `./` or `../`.
If `options.eval` is true, this is a string containing JavaScript code rather
than a path.
* `options` {Object}
Expand Down
5 changes: 3 additions & 2 deletions lib/internal/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -854,8 +854,9 @@ E('ERR_VM_MODULE_NOT_LINKED',
E('ERR_VM_MODULE_NOT_MODULE',
'Provided module is not an instance of Module', Error);
E('ERR_VM_MODULE_STATUS', 'Module status %s', Error);
E('ERR_WORKER_NEED_ABSOLUTE_PATH',
'The worker script filename must be an absolute path. Received "%s"',
E('ERR_WORKER_PATH',
'The worker script filename must be an absolute path or a relative ' +
'path starting with \'./\' or \'../\'. Received "%s"',
TypeError);
E('ERR_WORKER_UNSERIALIZABLE_ERROR',
'Serializing an uncaught exception failed', Error);
Expand Down
12 changes: 9 additions & 3 deletions lib/internal/worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const util = require('util');
const { Readable, Writable } = require('stream');
const {
ERR_INVALID_ARG_TYPE,
ERR_WORKER_NEED_ABSOLUTE_PATH,
ERR_WORKER_PATH,
ERR_WORKER_UNSERIALIZABLE_ERROR,
ERR_WORKER_UNSUPPORTED_EXTENSION,
} = require('internal/errors').codes;
Expand Down Expand Up @@ -212,9 +212,15 @@ class Worker extends EventEmitter {
}

if (!options.eval) {
if (!path.isAbsolute(filename)) {
throw new ERR_WORKER_NEED_ABSOLUTE_PATH(filename);
if (!path.isAbsolute(filename) &&
!filename.startsWith('./') &&
!filename.startsWith('../') &&
!filename.startsWith('.' + path.sep) &&
!filename.startsWith('..' + path.sep)) {
throw new ERR_WORKER_PATH(filename);
}
filename = path.resolve(filename);

const ext = path.extname(filename);
if (ext !== '.js' && ext !== '.mjs') {
throw new ERR_WORKER_UNSUPPORTED_EXTENSION(ext);
Expand Down
17 changes: 17 additions & 0 deletions test/parallel/test-worker-relative-path-double-dot.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Flags: --experimental-worker
'use strict';
const path = require('path');
const assert = require('assert');
const common = require('../common');
const { Worker, isMainThread, parentPort } = require('worker_threads');

if (isMainThread) {
const cwdName = path.relative('../', '.');
const relativePath = path.relative('.', __filename);
const w = new Worker(path.join('..', cwdName, relativePath));
w.on('message', common.mustCall((message) => {
assert.strictEqual(message, 'Hello, world!');
}));
} else {
parentPort.postMessage('Hello, world!');
}
15 changes: 15 additions & 0 deletions test/parallel/test-worker-relative-path.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Flags: --experimental-worker
'use strict';
const path = require('path');
const assert = require('assert');
const common = require('../common');
const { Worker, isMainThread, parentPort } = require('worker_threads');

if (isMainThread) {
const w = new Worker('./' + path.relative('.', __filename));
w.on('message', common.mustCall((message) => {
assert.strictEqual(message, 'Hello, world!');
}));
} else {
parentPort.postMessage('Hello, world!');
}
24 changes: 13 additions & 11 deletions test/parallel/test-worker-unsupported-path.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,11 @@
// Flags: --experimental-worker
'use strict';

const path = require('path');
const common = require('../common');
const assert = require('assert');
const { Worker } = require('worker_threads');

{
const expectedErr = common.expectsError({
code: 'ERR_WORKER_NEED_ABSOLUTE_PATH',
type: TypeError
}, 4);
assert.throws(() => { new Worker('a.js'); }, expectedErr);
assert.throws(() => { new Worker('b'); }, expectedErr);
assert.throws(() => { new Worker('c/d.js'); }, expectedErr);
assert.throws(() => { new Worker('a.mjs'); }, expectedErr);
}

{
const expectedErr = common.expectsError({
code: 'ERR_WORKER_UNSUPPORTED_EXTENSION',
Expand All @@ -25,3 +15,15 @@ const { Worker } = require('worker_threads');
assert.throws(() => { new Worker('/c.wasm'); }, expectedErr);
assert.throws(() => { new Worker('/d.txt'); }, expectedErr);
}

{
const expectedErr = common.expectsError({
code: 'ERR_WORKER_PATH',
type: TypeError
}, 4);
const existingRelPathNoDot = path.relative('.', __filename);
assert.throws(() => { new Worker(existingRelPathNoDot); }, expectedErr);
assert.throws(() => { new Worker('relative_no_dot'); }, expectedErr);
assert.throws(() => { new Worker('file:///file_url'); }, expectedErr);
assert.throws(() => { new Worker('https://www.url.com'); }, expectedErr);
}

0 comments on commit 206e5bf

Please sign in to comment.