worker: support relative paths

This commit adds support for relative paths in Worker.
Paths are relative to the current working directory.

PR-URL: https://github.com/nodejs/node/pull/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>
This commit is contained in:
itaysabato 2018-06-26 18:31:36 +03:00 committed by Benjamin Gruenbaum
parent 8326bea6c2
commit 8d33bbf168
7 changed files with 64 additions and 20 deletions

View File

@ -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

View File

@ -306,7 +306,9 @@ if (isMainThread) {
### new Worker(filename[, options])
* `filename` {string} The absolute path to the Workers main script.
* `filename` {string} The path to the Workers 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}

View File

@ -847,8 +847,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);

View File

@ -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;
@ -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);

View File

@ -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!');
}

View File

@ -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!');
}

View File

@ -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',
@ -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);
}