Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 71 additions & 6 deletions lib/tools/Config.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,76 @@ var Config = module.exports = {
}
};

function tokenizePm2ConfigArrayString(input) {
var tokens = [];
var token = '';
var quote = null;
var escape = false;
var stripQuoteDelimiters = false;

function flush() {
if (token && token.trim()) {
tokens.push(token);
}
token = '';
}

function isWhitespace(ch) {
return ch === ' ' || ch === '\t' || ch === '\n' || ch === '\r' || ch === '\f' || ch === '\v';
}

for (var i = 0; i < input.length; i++) {
var ch = input[i];

if (escape) {
token += ch;
escape = false;
continue;
}

if (ch === '\\') {
token += ch;
escape = true;
continue;
}

if (quote) {
if (ch === quote) {
if (!stripQuoteDelimiters) {
token += ch;
}
quote = null;
stripQuoteDelimiters = false;
continue;
}
token += ch;
continue;
}

if (ch === '"' || ch === "'") {
// Keep legacy behavior:
// - standalone quoted token: "a b" -> a b
// - quoted value inside existing token: --k="a b" -> --k="a b"
stripQuoteDelimiters = token.length === 0;
quote = ch;
if (!stripQuoteDelimiters) {
token += ch;
}
continue;
}

if (isWhitespace(ch)) {
flush();
continue;
}

token += ch;
}

flush();
return tokens;
}

/**
* Filter / Alias options
*/
Expand Down Expand Up @@ -200,12 +270,7 @@ Config._valid = function(key, value, sch){
// If first type is Array, but current is String, try to split them.
if(scht.length > 1 && type != scht[0] && type == '[object String]'){
if(scht[0] == '[object Array]') {
value = value.split(/([\w\-]+\="[^"]*")|([\w\-]+\='[^']*')|"([^"]*)"|'([^']*)'|\s/)
// unfortunately, js does not support lookahead RegExp (/(?<!\\)\s+/) now (until next ver).
//value = value.split(/((?<![\w\-])([\w\-]+\="[^"]*")|(?<![\w\-])([\w\-]+\='[^']*')|"([^"]*)"|'([^']*)'|\s )/)
.filter(function(v){
return v && v.trim();
});
value = tokenizePm2ConfigArrayString(value);
}
}

Expand Down
45 changes: 45 additions & 0 deletions test/programmatic/json_validation.mocha.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,49 @@ describe('JSON validation tests', function() {
done();
});

it('should split args string containing dashed flags (regression #6031)', function() {
var ret = Config.validateJSON({
script: 'app.js',
name: 'app',
args: 'start -c /app/nuxt.config.ts'
});

ret.errors.length.should.eql(0);
ret.config.args.should.eql(['start', '-c', '/app/nuxt.config.ts']);
});

it('should preserve quoted args when splitting string args', function() {
var ret = Config.validateJSON({
script: 'app.js',
name: 'app',
args: 'run --message "hello world" --single \'foo bar\' --another="baz qux"'
});

ret.errors.length.should.eql(0);
ret.config.args.should.eql([
'run',
'--message',
'hello world',
'--single',
'foo bar',
'--another=\"baz qux\"'
]);
});

it('should split node_args string into array', function() {
const cli = '--max-old-space-size=4096 --use-openssl-ca';

const expected = ['--max-old-space-size=4096', '--use-openssl-ca'];

const ret=Config.validateJSON({
script: 'app.js',
name: 'split-test',
node_args: cli
});

ret.errors.length.should.eql(0);

ret.config.node_args.should.eql(expected);
});

});