diff --git a/lib/create-config-gypi.js b/lib/create-config-gypi.js index d471da5169..5bf6ca945e 100644 --- a/lib/create-config-gypi.js +++ b/lib/create-config-gypi.js @@ -10,8 +10,13 @@ function parseConfigGypi (config) { config = config.replace(/#.*/g, '') // 2. join multiline strings config = config.replace(/'$\s+'/mg, '') - // 3. normalize string literals from ' into " - config = config.replace(/'/g, '"') + // 3. normalize string literals from ' into ", escaping any double-quote + // characters that appear inside a single-quoted string (e.g. GYP condition + // strings such as 'OS=="win"') so the result is still valid JSON + config = config.replace(/'(?:[^'\\]|\\.)*'/g, (str) => { + const inner = str.slice(1, -1).replace(/\\'/g, "'").replace(/"/g, '\\"') + return `"${inner}"` + }) return JSON.parse(config) } diff --git a/test/test-create-config-gypi.js b/test/test-create-config-gypi.js index 602fd3d678..30cd291b67 100644 --- a/test/test-create-config-gypi.js +++ b/test/test-create-config-gypi.js @@ -76,4 +76,10 @@ describe('create-config-gypi', function () { const config = parseConfigGypi(str) assert.deepStrictEqual(config, { variables: { multiline: 'AB' } }) }) + + it('config.gypi parsing with double quotes inside single-quoted strings', function () { + const str = '{\'variables\': {\'cond\': \'OS=="win"\', \'flags\': \'-DFOO="x"\'}}' + const config = parseConfigGypi(str) + assert.deepStrictEqual(config, { variables: { cond: 'OS=="win"', flags: '-DFOO="x"' } }) + }) })