From 1e7e6731393d47014ba8d495790fdf59574abec4 Mon Sep 17 00:00:00 2001 From: Jon Jensen Date: Tue, 31 Mar 2015 22:35:50 -0600 Subject: [PATCH] fix loc.end for JSXEmptyExpression ensure that it correctly handles line terminators, whether part of the empty expression, or block comment inside it. this is particularly important for recast or other tools that care about comments inside jsx expressions. recast in particular will error out if there is a loc mismatch between the comment and its corresponding node. see https://github.com/benjamn/recast/issues/175 for more context. the AST for the newly added tests differs only in its JSXEmptyExpression loc.end data when run against the old code: ``` 1058c1058 < end: { line: 1, column: 6 } --- > end: { line: 2, column: 1 } 1194c1194 < end: { line: 1, column: 38 } --- > end: { line: 5, column: 11 } ``` --- esprima.js | 16 +++++- test/fbtest.js | 2 + test/fbtest.rec.js | 138 ++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 152 insertions(+), 4 deletions(-) diff --git a/esprima.js b/esprima.js index 219bd4b8bf4..0ceacf031d6 100644 --- a/esprima.js +++ b/esprima.js @@ -7008,9 +7008,19 @@ } function parseJSXEmptyExpression() { - var marker = markerCreatePreserveWhitespace(); - while (source.charAt(index) !== '}') { - index++; + var ch, marker = markerCreatePreserveWhitespace(); + while (index < length) { + ch = source.charCodeAt(index); + if (ch === 125) { + break; + } else if (isLineTerminator(ch)) { + if (ch === 13 && source.charCodeAt(index + 1) === 10) { + ++index; + } + ++lineNumber; + lineStart = index; + } + ++index; } return markerApply(marker, delegate.createJSXEmptyExpression()); } diff --git a/test/fbtest.js b/test/fbtest.js index 58404b93c23..1e5798eefff 100644 --- a/test/fbtest.js +++ b/test/fbtest.js @@ -38,7 +38,9 @@ module.exports = { '\nbar\nbaz\r\n', ' : } />', '{}', + '{\r\n}', '{/* this is a comment */}', + '{/* this\nis\na\nmulti-line\ncomment */}', '
@test content
', '

7x invalid-js-identifier
', ' right=monkeys />', diff --git a/test/fbtest.rec.js b/test/fbtest.rec.js index 4f8e53a3858..4c5fe23be79 100644 --- a/test/fbtest.rec.js +++ b/test/fbtest.rec.js @@ -4,7 +4,7 @@ * tests/fbtest.js and run tools/generate-fbtest.js */ -var numTests = 221 +var numTests = 223 var testFixture; var fbTestFixture = { @@ -1008,6 +1008,74 @@ var fbTestFixture = { end: { line: 1, column: 9 } } }, + '{\r\n}': { + type: 'ExpressionStatement', + expression: { + type: 'JSXElement', + openingElement: { + type: 'JSXOpeningElement', + name: { + type: 'JSXIdentifier', + name: 'a', + range: [1, 2], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 2 } + } + }, + selfClosing: false, + attributes: [], + range: [0, 3], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, + closingElement: { + type: 'JSXClosingElement', + name: { + type: 'JSXIdentifier', + name: 'a', + range: [9, 10], + loc: { + start: { line: 2, column: 3 }, + end: { line: 2, column: 4 } + } + }, + range: [7, 11], + loc: { + start: { line: 2, column: 1 }, + end: { line: 2, column: 5 } + } + }, + children: [{ + type: 'JSXExpressionContainer', + expression: { + type: 'JSXEmptyExpression', + range: [4, 6], + loc: { + start: { line: 1, column: 4 }, + end: { line: 2, column: 1 } + } + }, + range: [3, 7], + loc: { + start: { line: 1, column: 3 }, + end: { line: 2, column: 1 } + } + }], + range: [0, 11], + loc: { + start: { line: 1, column: 0 }, + end: { line: 2, column: 5 } + } + }, + range: [0, 11], + loc: { + start: { line: 1, column: 0 }, + end: { line: 2, column: 5 } + } + }, '{/* this is a comment */}': { type: 'ExpressionStatement', expression: { @@ -1076,6 +1144,74 @@ var fbTestFixture = { end: { line: 1, column: 32 } } }, + '{/* this\nis\na\nmulti-line\ncomment */}': { + type: 'ExpressionStatement', + expression: { + type: 'JSXElement', + openingElement: { + type: 'JSXOpeningElement', + name: { + type: 'JSXIdentifier', + name: 'a', + range: [1, 2], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 2 } + } + }, + selfClosing: false, + attributes: [], + range: [0, 3], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, + closingElement: { + type: 'JSXClosingElement', + name: { + type: 'JSXIdentifier', + name: 'a', + range: [41, 42], + loc: { + start: { line: 5, column: 13 }, + end: { line: 5, column: 14 } + } + }, + range: [39, 43], + loc: { + start: { line: 5, column: 11 }, + end: { line: 5, column: 15 } + } + }, + children: [{ + type: 'JSXExpressionContainer', + expression: { + type: 'JSXEmptyExpression', + range: [4, 38], + loc: { + start: { line: 1, column: 4 }, + end: { line: 5, column: 11 } + } + }, + range: [3, 39], + loc: { + start: { line: 1, column: 3 }, + end: { line: 5, column: 11 } + } + }], + range: [0, 43], + loc: { + start: { line: 1, column: 0 }, + end: { line: 5, column: 15 } + } + }, + range: [0, 43], + loc: { + start: { line: 1, column: 0 }, + end: { line: 5, column: 15 } + } + }, '
@test content
': { type: 'ExpressionStatement', expression: {