From 221cbcfe29c07330e99cb1121121c4c20b8462a9 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Tue, 5 Apr 2016 11:24:59 -0700 Subject: [PATCH 1/8] Accepted valid baselines --- .../baselines/reference/tsxErrorRecovery3.js | 6 ++-- .../reference/tsxExternalModuleEmit2.js | 2 +- tests/baselines/reference/tsxReactEmit1.js | 31 +++++++++---------- tests/baselines/reference/tsxReactEmit2.js | 6 ++-- tests/baselines/reference/tsxReactEmit3.js | 9 +----- tests/baselines/reference/tsxReactEmit4.js | 2 +- tests/baselines/reference/tsxReactEmit7.js | 18 +++++------ 7 files changed, 31 insertions(+), 43 deletions(-) diff --git a/tests/baselines/reference/tsxErrorRecovery3.js b/tests/baselines/reference/tsxErrorRecovery3.js index 93b34a14c19..7c7b0739661 100644 --- a/tests/baselines/reference/tsxErrorRecovery3.js +++ b/tests/baselines/reference/tsxErrorRecovery3.js @@ -12,8 +12,6 @@ var x =
//// [file1.js] -React.createElement("div", null) - , - React.createElement("div", null); +React.createElement("div", null), React.createElement("div", null); //// [file2.js] -var x = React.createElement("div", null), React.createElement("div", null); +var x = (React.createElement("div", null), React.createElement("div", null)); diff --git a/tests/baselines/reference/tsxExternalModuleEmit2.js b/tests/baselines/reference/tsxExternalModuleEmit2.js index 2233c5181cb..669152e02c3 100644 --- a/tests/baselines/reference/tsxExternalModuleEmit2.js +++ b/tests/baselines/reference/tsxExternalModuleEmit2.js @@ -21,6 +21,6 @@ declare var Foo, React; "use strict"; var mod_1 = require('mod'); // Should see mod_1['default'] in emit here -React.createElement(Foo, {handler: mod_1["default"]}); +React.createElement(Foo, { handler: mod_1["default"] }); // Should see mod_1['default'] in emit here React.createElement(Foo, React.__spread({}, mod_1["default"])); diff --git a/tests/baselines/reference/tsxReactEmit1.js b/tests/baselines/reference/tsxReactEmit1.js index f62a7bdc47d..49fbc38fdec 100644 --- a/tests/baselines/reference/tsxReactEmit1.js +++ b/tests/baselines/reference/tsxReactEmit1.js @@ -44,17 +44,17 @@ var whitespace3 =
//// [file.js] var p; var selfClosed1 = React.createElement("div", null); -var selfClosed2 = React.createElement("div", {x: "1"}); -var selfClosed3 = React.createElement("div", {x: '1'}); -var selfClosed4 = React.createElement("div", {x: "1", y: '0'}); -var selfClosed5 = React.createElement("div", {x: 0, y: '0'}); -var selfClosed6 = React.createElement("div", {x: "1", y: '0'}); -var selfClosed7 = React.createElement("div", {x: p, y: 'p', b: true}); +var selfClosed2 = React.createElement("div", { x: "1" }); +var selfClosed3 = React.createElement("div", { x: '1' }); +var selfClosed4 = React.createElement("div", { x: "1", y: '0' }); +var selfClosed5 = React.createElement("div", { x: 0, y: '0' }); +var selfClosed6 = React.createElement("div", { x: "1", y: '0' }); +var selfClosed7 = React.createElement("div", { x: p, y: 'p', b: true }); var openClosed1 = React.createElement("div", null); -var openClosed2 = React.createElement("div", {n: 'm'}, "foo"); -var openClosed3 = React.createElement("div", {n: 'm'}, p); -var openClosed4 = React.createElement("div", {n: 'm'}, p < p); -var openClosed5 = React.createElement("div", {n: 'm', b: true}, p > p); +var openClosed2 = React.createElement("div", { n: 'm' }, "foo"); +var openClosed3 = React.createElement("div", { n: 'm' }, p); +var openClosed4 = React.createElement("div", { n: 'm' }, p < p); +var openClosed5 = React.createElement("div", { n: 'm', b: true }, p > p); var SomeClass = (function () { function SomeClass() { } @@ -63,15 +63,12 @@ var SomeClass = (function () { var rewrites1 = React.createElement("div", null, function () { return _this; }); var rewrites2 = React.createElement("div", null, [p].concat(p, [p])); var rewrites3 = React.createElement("div", null, { p: p }); - var rewrites4 = React.createElement("div", {a: function () { return _this; }}); - var rewrites5 = React.createElement("div", {a: [p].concat(p, [p])}); - var rewrites6 = React.createElement("div", {a: { p: p }}); + var rewrites4 = React.createElement("div", { a: function () { return _this; } }); + var rewrites5 = React.createElement("div", { a: [p].concat(p, [p]) }); + var rewrites6 = React.createElement("div", { a: { p: p } }); }; return SomeClass; }()); var whitespace1 = React.createElement("div", null, " "); -var whitespace2 = React.createElement("div", null, - " ", - p, - " "); +var whitespace2 = React.createElement("div", null, " ", p, " "); var whitespace3 = React.createElement("div", null, p); diff --git a/tests/baselines/reference/tsxReactEmit2.js b/tests/baselines/reference/tsxReactEmit2.js index fd7fff16976..0776f74fef9 100644 --- a/tests/baselines/reference/tsxReactEmit2.js +++ b/tests/baselines/reference/tsxReactEmit2.js @@ -19,6 +19,6 @@ var spreads5 =
{p2}
; var p1, p2, p3; var spreads1 = React.createElement("div", React.__spread({}, p1), p2); var spreads2 = React.createElement("div", React.__spread({}, p1), p2); -var spreads3 = React.createElement("div", React.__spread({x: p3}, p1), p2); -var spreads4 = React.createElement("div", React.__spread({}, p1, {x: p3}), p2); -var spreads5 = React.createElement("div", React.__spread({x: p2}, p1, {y: p3}), p2); +var spreads3 = React.createElement("div", React.__spread({ x: p3 }, p1), p2); +var spreads4 = React.createElement("div", React.__spread({}, p1, { x: p3 }), p2); +var spreads5 = React.createElement("div", React.__spread({ x: p2 }, p1, { y: p3 }), p2); diff --git a/tests/baselines/reference/tsxReactEmit3.js b/tests/baselines/reference/tsxReactEmit3.js index 07a8f22761f..bd42177e187 100644 --- a/tests/baselines/reference/tsxReactEmit3.js +++ b/tests/baselines/reference/tsxReactEmit3.js @@ -8,11 +8,4 @@ declare var Foo, Bar, baz; q s ; //// [test.js] -React.createElement(Foo, null, - " ", - React.createElement(Bar, null, " q "), - " ", - React.createElement(Bar, null), - " s ", - React.createElement(Bar, null), - React.createElement(Bar, null)); +React.createElement(Foo, null, " ", React.createElement(Bar, null, " q "), " ", React.createElement(Bar, null), " s ", React.createElement(Bar, null), React.createElement(Bar, null)); diff --git a/tests/baselines/reference/tsxReactEmit4.js b/tests/baselines/reference/tsxReactEmit4.js index d61cea24d2c..d7b9c48d57f 100644 --- a/tests/baselines/reference/tsxReactEmit4.js +++ b/tests/baselines/reference/tsxReactEmit4.js @@ -21,4 +21,4 @@ var spread1 =
; var p; var openClosed1 = React.createElement("div", null, blah); // Should emit React.__spread({}, p, {x: 0}) -var spread1 = React.createElement("div", React.__spread({}, p, {x: 0})); +var spread1 = React.createElement("div", React.__spread({}, p, { x: 0 })); diff --git a/tests/baselines/reference/tsxReactEmit7.js b/tests/baselines/reference/tsxReactEmit7.js index 44d28c2dd9c..c119585c1f6 100644 --- a/tests/baselines/reference/tsxReactEmit7.js +++ b/tests/baselines/reference/tsxReactEmit7.js @@ -21,13 +21,13 @@ var e =
; //// [file.js] -var m = React.createElement("div", {"x-y": "val"}); -var n = React.createElement("div", {"xx-y": "val"}); -var o = React.createElement("div", {"x-yy": "val"}); -var p = React.createElement("div", {"xx-yy": "val"}); +var m = React.createElement("div", { "x-y": "val" }); +var n = React.createElement("div", { "xx-y": "val" }); +var o = React.createElement("div", { "x-yy": "val" }); +var p = React.createElement("div", { "xx-yy": "val" }); // Investigation -var a = React.createElement("div", {x: "val"}); -var b = React.createElement("div", {xx: "val"}); -var c = React.createElement("div", {xxx: "val"}); -var d = React.createElement("div", {xxxx: "val"}); -var e = React.createElement("div", {xxxxx: "val"}); +var a = React.createElement("div", { x: "val" }); +var b = React.createElement("div", { xx: "val" }); +var c = React.createElement("div", { xxx: "val" }); +var d = React.createElement("div", { xxxx: "val" }); +var e = React.createElement("div", { xxxxx: "val" }); From 0b2264cc544930b5f64c1f131f6af522bf7485d9 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Tue, 5 Apr 2016 16:50:19 -0700 Subject: [PATCH 2/8] Additional fixes for React emit. --- src/compiler/factory.ts | 23 +++-- src/compiler/printer.ts | 85 ++++++++++++------- src/compiler/transformers/jsx.ts | 32 ++++--- .../baselines/reference/jsxReactTestSuite.js | 5 +- .../reference/keywordInJsxIdentifier.js | 8 +- .../reference/reactNamespaceInvalidInput.js | 2 +- .../reference/reactNamespaceJSXEmit.js | 6 +- .../reactNamespaceMissingDeclaration.js | 2 +- .../baselines/reference/tsxErrorRecovery3.js | 4 +- tests/baselines/reference/tsxReactEmit1.js | 5 +- tests/baselines/reference/tsxReactEmit3.js | 9 +- tests/baselines/reference/tsxReactEmit5.js | 2 +- tests/baselines/reference/tsxReactEmit6.js | 2 +- .../reference/tsxReactEmitEntities.js | 2 +- .../reference/tsxReactEmitNesting.js | 32 ++++--- .../reference/tsxReactEmitWhitespace.js | 8 +- .../reference/tsxReactEmitWhitespace2.js | 14 +-- 17 files changed, 148 insertions(+), 93 deletions(-) diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index fd7bee61213..11985e17de8 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -66,7 +66,7 @@ namespace ts { // We don't use "clone" from core.ts here, as we need to preserve the prototype chain of // the original node. We also need to exclude specific properties and only include own- // properties (to skip members already defined on the shared prototype). - const clone = createSynthesizedNode(node.kind); + const clone = createNode(node.kind, /*location*/ undefined); clone.flags = node.flags; clone.original = node; @@ -784,17 +784,25 @@ namespace ts { ); } - export function createJsxSpread(reactNamespace: string, segments: Expression[]) { + function createReactNamespace(reactNamespace: string, parent: JsxOpeningLikeElement) { + // Create an identifier and give it a parent. This allows us to resolve the react + // namespace during emit. + const react = createIdentifier(reactNamespace || "React"); + react.parent = parent; + return react; + } + + export function createReactSpread(reactNamespace: string, segments: Expression[], parentElement: JsxOpeningLikeElement) { return createCall( createPropertyAccess( - createIdentifier(reactNamespace || "React"), + createReactNamespace(reactNamespace, parentElement), "__spread" ), segments ); } - export function createJsxCreateElement(reactNamespace: string, tagName: Expression, props: Expression, children: Expression[]): LeftHandSideExpression { + export function createReactCreateElement(reactNamespace: string, tagName: Expression, props: Expression, children: Expression[], parentElement: JsxOpeningLikeElement, location: TextRange): LeftHandSideExpression { const argumentsList = [tagName]; if (props) { argumentsList.push(props); @@ -805,15 +813,16 @@ namespace ts { argumentsList.push(createNull()); } - addRange(argumentsList, children); + addNodes(argumentsList, children, /*startOnNewLine*/ children.length > 1); } return createCall( createPropertyAccess( - createIdentifier(reactNamespace || "React"), + createReactNamespace(reactNamespace, parentElement), "createElement" ), - argumentsList + argumentsList, + location ); } diff --git a/src/compiler/printer.ts b/src/compiler/printer.ts index 54b4f0b2d3f..438fe445109 100644 --- a/src/compiler/printer.ts +++ b/src/compiler/printer.ts @@ -1017,9 +1017,7 @@ const _super = (function (geti, seti) { function emitNewExpression(node: NewExpression) { write("new "); emitExpression(node.expression); - if (node.arguments) { - emitExpressionList(node, node.arguments, ListFormat.NewExpressionArguments); - } + emitExpressionList(node, node.arguments, ListFormat.NewExpressionArguments); } function emitTaggedTemplateExpression(node: TaggedTemplateExpression) { @@ -1536,7 +1534,7 @@ const _super = (function (geti, seti) { write("interface "); emit(node.name); emitTypeParameters(node, node.typeParameters); - emitList(node, node.heritageClauses, ListFormat.SingleLine); + emitList(node, node.heritageClauses, ListFormat.HeritageClauses); write(" {"); emitList(node, node.members, ListFormat.InterfaceMembers); write("}"); @@ -1722,7 +1720,7 @@ const _super = (function (geti, seti) { function emitJsxSelfClosingElement(node: JsxSelfClosingElement) { write("<"); - emit(node.tagName); + emitJsxTagName(node.tagName); write(" "); emitList(node, node.attributes, ListFormat.JsxElementAttributes); write("/>"); @@ -1730,7 +1728,7 @@ const _super = (function (geti, seti) { function emitJsxOpeningElement(node: JsxOpeningElement) { write("<"); - emit(node.tagName); + emitJsxTagName(node.tagName); writeIfAny(node.attributes, " "); emitList(node, node.attributes, ListFormat.JsxElementAttributes); write(">"); @@ -1742,7 +1740,7 @@ const _super = (function (geti, seti) { function emitJsxClosingElement(node: JsxClosingElement) { write(""); } @@ -1758,9 +1756,20 @@ const _super = (function (geti, seti) { } function emitJsxExpression(node: JsxExpression) { - write("{"); - emitExpression(node.expression); - write("}"); + if (node.expression) { + write("{"); + emitExpression(node.expression); + write("}"); + } + } + + function emitJsxTagName(node: EntityName) { + if (node.kind === SyntaxKind.Identifier) { + emitExpression(node); + } + else { + emit(node); + } } // @@ -2168,6 +2177,7 @@ const _super = (function (geti, seti) { // Emit each child. let previousSibling: Node; + let shouldDecreaseIndentAfterEmit: boolean; const delimiter = getDelimiter(format); for (let i = 0; i < count; i++) { const child = children[start + i]; @@ -2178,6 +2188,13 @@ const _super = (function (geti, seti) { // Write either a line terminator or whitespace to separate the elements. if (shouldWriteSeparatingLineTerminator(previousSibling, child, format)) { + // If a synthesized node in a single-line list starts on a new + // line, we should increase the indent. + if ((format & (ListFormat.LinesMask | ListFormat.Indented)) === ListFormat.SingleLine) { + increaseIndent(); + shouldDecreaseIndentAfterEmit = true; + } + writeLine(); shouldEmitInterveningComments = false; } @@ -2196,6 +2213,11 @@ const _super = (function (geti, seti) { // Emit this child. emit(child); + if (shouldDecreaseIndentAfterEmit) { + decreaseIndent(); + shouldDecreaseIndentAfterEmit = false; + } + previousSibling = child; } @@ -2322,7 +2344,7 @@ const _super = (function (geti, seti) { } } else { - return false; + return nextNode.startsOnNewLine; } } @@ -2619,40 +2641,43 @@ const _super = (function (geti, seti) { None = 0, // Line separators - SingleLine = 1 << 0, // Prints the list on a single line (default). - MultiLine = 1 << 1, // Prints the list on multiple lines. - PreserveLines = 1 << 2, // Prints the list using line preservation if possible. + SingleLine = 0, // Prints the list on a single line (default). + MultiLine = 1 << 0, // Prints the list on multiple lines. + PreserveLines = 1 << 1, // Prints the list using line preservation if possible. LinesMask = SingleLine | MultiLine | PreserveLines, // Delimiters NotDelimited = 0, // There is no delimiter between list items (default). - BarDelimited = 1 << 3, // Each list item is space-and-bar (" |") delimited. - AmpersandDelimited = 1 << 4, // Each list item is space-and-ampersand (" &") delimited. - CommaDelimited = 1 << 5, // Each list item is comma (",") delimited. - AllowTrailingComma = 1 << 6, // Write a trailing comma (",") if present. + BarDelimited = 1 << 2, // Each list item is space-and-bar (" |") delimited. + AmpersandDelimited = 1 << 3, // Each list item is space-and-ampersand (" &") delimited. + CommaDelimited = 1 << 4, // Each list item is comma (",") delimited. DelimitersMask = BarDelimited | AmpersandDelimited | CommaDelimited, + AllowTrailingComma = 1 << 5, // Write a trailing comma (",") if present. + // Whitespace - Indented = 1 << 7, // The list should be indented. - SpaceBetweenBraces = 1 << 8, // Inserts a space after the opening brace and before the closing brace. - SpaceBetweenSiblings = 1 << 9, // Inserts a space between each sibling node. + Indented = 1 << 6, // The list should be indented. + SpaceBetweenBraces = 1 << 7, // Inserts a space after the opening brace and before the closing brace. + SpaceBetweenSiblings = 1 << 8, // Inserts a space between each sibling node. // Brackets/Braces - Braces = 1 << 10, // The list is surrounded by "{" and "}". - Parenthesis = 1 << 11, // The list is surrounded by "(" and ")". - AngleBrackets = 1 << 12, // The list is surrounded by "<" and ">". - SquareBrackets = 1 << 13, // The list is surrounded by "[" and "]". - OptionalIfUndefined = 1 << 14, // Do not emit brackets if the list is undefined. - OptionalIfEmpty = 1 << 15, // Do not emit brackets if the list is empty. - Optional = OptionalIfUndefined | OptionalIfEmpty, + Braces = 1 << 9, // The list is surrounded by "{" and "}". + Parenthesis = 1 << 10, // The list is surrounded by "(" and ")". + AngleBrackets = 1 << 11, // The list is surrounded by "<" and ">". + SquareBrackets = 1 << 12, // The list is surrounded by "[" and "]". BracketsMask = Braces | Parenthesis | AngleBrackets | SquareBrackets, + OptionalIfUndefined = 1 << 13, // Do not emit brackets if the list is undefined. + OptionalIfEmpty = 1 << 14, // Do not emit brackets if the list is empty. + Optional = OptionalIfUndefined | OptionalIfEmpty, + // Other - PreferNewLine = 1 << 16, // Prefer adding a LineTerminator between synthesized nodes. - NoTrailingNewLine = 1 << 17, // Do not emit a trailing NewLine for a MultiLine list. + PreferNewLine = 1 << 15, // Prefer adding a LineTerminator between synthesized nodes. + NoTrailingNewLine = 1 << 16, // Do not emit a trailing NewLine for a MultiLine list. // Precomputed Formats Modifiers = SingleLine | SpaceBetweenSiblings, + HeritageClauses = SingleLine | SpaceBetweenSiblings, TypeLiteralMembers = MultiLine | Indented, TupleTypeElements = CommaDelimited | SpaceBetweenSiblings | SingleLine | Indented, UnionTypeConstituents = BarDelimited | SpaceBetweenSiblings | SingleLine, diff --git a/src/compiler/transformers/jsx.ts b/src/compiler/transformers/jsx.ts index 9fd2eb0ebb1..7dfe84b0b11 100644 --- a/src/compiler/transformers/jsx.ts +++ b/src/compiler/transformers/jsx.ts @@ -33,10 +33,10 @@ namespace ts { function visitorWorker(node: Node): VisitResult { switch (node.kind) { case SyntaxKind.JsxElement: - return visitJsxElement(node); + return visitJsxElement(node, /*isChild*/ false); case SyntaxKind.JsxSelfClosingElement: - return visitJsxSelfClosingElement(node); + return visitJsxSelfClosingElement(node, /*isChild*/ false); case SyntaxKind.JsxExpression: return visitJsxExpression(node); @@ -56,10 +56,10 @@ namespace ts { return visitJsxExpression(node); case SyntaxKind.JsxElement: - return visitJsxElement(node); + return visitJsxElement(node, /*isChild*/ true); case SyntaxKind.JsxSelfClosingElement: - return visitJsxSelfClosingElement(node); + return visitJsxSelfClosingElement(node, /*isChild*/ true); default: Debug.failBadSyntaxKind(node); @@ -67,15 +67,15 @@ namespace ts { } } - function visitJsxElement(node: JsxElement) { - return visitJsxOpeningLikeElement(node.openingElement, node.children); + function visitJsxElement(node: JsxElement, isChild: boolean) { + return visitJsxOpeningLikeElement(node.openingElement, node.children, isChild, /*location*/ node); } - function visitJsxSelfClosingElement(node: JsxSelfClosingElement) { - return visitJsxOpeningLikeElement(node, /*children*/ undefined); + function visitJsxSelfClosingElement(node: JsxSelfClosingElement, isChild: boolean) { + return visitJsxOpeningLikeElement(node, /*children*/ undefined, isChild, /*location*/ node); } - function visitJsxOpeningLikeElement(node: JsxOpeningLikeElement, children: JsxChild[]) { + function visitJsxOpeningLikeElement(node: JsxOpeningLikeElement, children: JsxChild[], isChild: boolean, location: TextRange) { const tagName = getTagName(node); let objectProperties: Expression; const attrs = node.attributes; @@ -102,15 +102,23 @@ namespace ts { // Either emit one big object literal (no spread attribs), or // a call to React.__spread objectProperties = singleOrUndefined(segments) - || createJsxSpread(compilerOptions.reactNamespace, segments); + || createReactSpread(compilerOptions.reactNamespace, segments, node); } - return createJsxCreateElement( + const element = createReactCreateElement( compilerOptions.reactNamespace, tagName, objectProperties, - filter(map(children, transformJsxChildToExpression), isDefined) + filter(map(children, transformJsxChildToExpression), isDefined), + node, + location ); + + if (isChild) { + startOnNewLine(element); + } + + return element; } function transformJsxSpreadAttributeToExpression(node: JsxSpreadAttribute) { diff --git a/tests/baselines/reference/jsxReactTestSuite.js b/tests/baselines/reference/jsxReactTestSuite.js index 18013d4be9b..392f1736407 100644 --- a/tests/baselines/reference/jsxReactTestSuite.js +++ b/tests/baselines/reference/jsxReactTestSuite.js @@ -148,7 +148,10 @@ var x =
); -(
+(
); diff --git a/tests/baselines/reference/keywordInJsxIdentifier.js b/tests/baselines/reference/keywordInJsxIdentifier.js index 39f33449dad..6009e1980e6 100644 --- a/tests/baselines/reference/keywordInJsxIdentifier.js +++ b/tests/baselines/reference/keywordInJsxIdentifier.js @@ -8,7 +8,7 @@ declare var React: any; //// [keywordInJsxIdentifier.js] -React.createElement("foo", {"class-id": true}); -React.createElement("foo", {class: true}); -React.createElement("foo", {"class-id": "1"}); -React.createElement("foo", {class: "1"}); +React.createElement("foo", { "class-id": true }); +React.createElement("foo", { class: true }); +React.createElement("foo", { "class-id": "1" }); +React.createElement("foo", { class: "1" }); diff --git a/tests/baselines/reference/reactNamespaceInvalidInput.js b/tests/baselines/reference/reactNamespaceInvalidInput.js index bf079d6b9a8..69918fe976f 100644 --- a/tests/baselines/reference/reactNamespaceInvalidInput.js +++ b/tests/baselines/reference/reactNamespaceInvalidInput.js @@ -4,4 +4,4 @@ //// [reactNamespaceInvalidInput.js] -my-React-Lib.createElement("foo", {data: true}); +my-React-Lib.createElement("foo", { data: true }); diff --git a/tests/baselines/reference/reactNamespaceJSXEmit.js b/tests/baselines/reference/reactNamespaceJSXEmit.js index 26967d56b7b..29fd6809ce9 100644 --- a/tests/baselines/reference/reactNamespaceJSXEmit.js +++ b/tests/baselines/reference/reactNamespaceJSXEmit.js @@ -13,8 +13,8 @@ declare var x: any; //// [reactNamespaceJSXEmit.js] -myReactLib.createElement("foo", {data: true}); -myReactLib.createElement(Bar, {x: x}); +myReactLib.createElement("foo", { data: true }); +myReactLib.createElement(Bar, { x: x }); myReactLib.createElement("x-component", null); myReactLib.createElement(Bar, myReactLib.__spread({}, x)); -myReactLib.createElement(Bar, myReactLib.__spread({}, x, {y: 2})); +myReactLib.createElement(Bar, myReactLib.__spread({}, x, { y: 2 })); diff --git a/tests/baselines/reference/reactNamespaceMissingDeclaration.js b/tests/baselines/reference/reactNamespaceMissingDeclaration.js index d972f319f8f..8faeffa6496 100644 --- a/tests/baselines/reference/reactNamespaceMissingDeclaration.js +++ b/tests/baselines/reference/reactNamespaceMissingDeclaration.js @@ -5,4 +5,4 @@ //// [reactNamespaceMissingDeclaration.js] // Error myReactLib not declared -myReactLib.createElement("foo", {data: true}); +myReactLib.createElement("foo", { data: true }); diff --git a/tests/baselines/reference/tsxErrorRecovery3.js b/tests/baselines/reference/tsxErrorRecovery3.js index 7c7b0739661..0e0d3d072a6 100644 --- a/tests/baselines/reference/tsxErrorRecovery3.js +++ b/tests/baselines/reference/tsxErrorRecovery3.js @@ -12,6 +12,8 @@ var x =
//// [file1.js] -React.createElement("div", null), React.createElement("div", null); +React.createElement("div", null) + , + React.createElement("div", null); //// [file2.js] var x = (React.createElement("div", null), React.createElement("div", null)); diff --git a/tests/baselines/reference/tsxReactEmit1.js b/tests/baselines/reference/tsxReactEmit1.js index 49fbc38fdec..20a91b3fe89 100644 --- a/tests/baselines/reference/tsxReactEmit1.js +++ b/tests/baselines/reference/tsxReactEmit1.js @@ -70,5 +70,8 @@ var SomeClass = (function () { return SomeClass; }()); var whitespace1 = React.createElement("div", null, " "); -var whitespace2 = React.createElement("div", null, " ", p, " "); +var whitespace2 = React.createElement("div", null, + " ", + p, + " "); var whitespace3 = React.createElement("div", null, p); diff --git a/tests/baselines/reference/tsxReactEmit3.js b/tests/baselines/reference/tsxReactEmit3.js index bd42177e187..155a316e078 100644 --- a/tests/baselines/reference/tsxReactEmit3.js +++ b/tests/baselines/reference/tsxReactEmit3.js @@ -8,4 +8,11 @@ declare var Foo, Bar, baz; q s ; //// [test.js] -React.createElement(Foo, null, " ", React.createElement(Bar, null, " q "), " ", React.createElement(Bar, null), " s ", React.createElement(Bar, null), React.createElement(Bar, null)); +React.createElement(Foo, null, + " ", + React.createElement(Bar, null, " q "), + " ", + React.createElement(Bar, null), + " s ", + React.createElement(Bar, null), + React.createElement(Bar, null)); diff --git a/tests/baselines/reference/tsxReactEmit5.js b/tests/baselines/reference/tsxReactEmit5.js index 06b05f67d63..e5c781e6a8f 100644 --- a/tests/baselines/reference/tsxReactEmit5.js +++ b/tests/baselines/reference/tsxReactEmit5.js @@ -27,4 +27,4 @@ var test_1 = require("./test"); // Should emit test_1.React.createElement // and React.__spread var foo; -var spread1 = test_1.React.createElement("div", test_1.React.__spread({x: ''}, foo, {y: ''})); +var spread1 = test_1.React.createElement("div", test_1.React.__spread({ x: '' }, foo, { y: '' })); diff --git a/tests/baselines/reference/tsxReactEmit6.js b/tests/baselines/reference/tsxReactEmit6.js index 4f583929004..7a69ab6ae6d 100644 --- a/tests/baselines/reference/tsxReactEmit6.js +++ b/tests/baselines/reference/tsxReactEmit6.js @@ -36,7 +36,7 @@ var M; // Should emit M.React.createElement // and M.React.__spread var foo; - var spread1 = M.React.createElement("div", M.React.__spread({x: ''}, foo, {y: ''})); + var spread1 = M.React.createElement("div", M.React.__spread({ x: '' }, foo, { y: '' })); // Quotes var x = M.React.createElement("div", null, "This \"quote\" thing"); })(M || (M = {})); diff --git a/tests/baselines/reference/tsxReactEmitEntities.js b/tests/baselines/reference/tsxReactEmitEntities.js index a20f3380bf7..2a5c1ec4963 100644 --- a/tests/baselines/reference/tsxReactEmitEntities.js +++ b/tests/baselines/reference/tsxReactEmitEntities.js @@ -12,5 +12,5 @@ declare var React: any; //// [file.js] -React.createElement("div", null, "Dot goes here: ยท ¬AnEntity; "); +React.createElement("div", null, "Dot goes here: \u00B7 ¬AnEntity; "); React.createElement("div", null, "Be careful of \"-ed strings!"); diff --git a/tests/baselines/reference/tsxReactEmitNesting.js b/tests/baselines/reference/tsxReactEmitNesting.js index 53abc04aa9b..29e948f687b 100644 --- a/tests/baselines/reference/tsxReactEmitNesting.js +++ b/tests/baselines/reference/tsxReactEmitNesting.js @@ -38,23 +38,21 @@ let render = (ctrl, model) => //// [file.js] // A simple render function with nesting and control statements var render = function (ctrl, model) { - return vdom.createElement("section", {class: "todoapp"}, - vdom.createElement("header", {class: "header"}, - vdom.createElement("h1", null, "todos "), - vdom.createElement("input", {class: "new-todo", autofocus: true, autocomplete: "off", placeholder: "What needs to be done?", value: model.newTodo, onKeyup: ctrl.addTodo.bind(ctrl, model)})), - vdom.createElement("section", {class: "main", style: { display: (model.todos && model.todos.length) ? "block" : "none" }}, - vdom.createElement("input", {class: "toggle-all", type: "checkbox", onChange: ctrl.toggleAll.bind(ctrl)}), - vdom.createElement("ul", {class: "todo-list"}, model.filteredTodos.map(function (todo) { - return vdom.createElement("li", {class: { todo: true, completed: todo.completed, editing: todo == model.editedTodo }}, - vdom.createElement("div", {class: "view"}, + return vdom.createElement("section", { class: "todoapp" }, + vdom.createElement("header", { class: "header" }, + vdom.createElement("h1", null, "todos "), + vdom.createElement("input", { class: "new-todo", autofocus: true, autocomplete: "off", placeholder: "What needs to be done?", value: model.newTodo, onKeyup: ctrl.addTodo.bind(ctrl, model) })), + vdom.createElement("section", { class: "main", style: { display: (model.todos && model.todos.length) ? "block" : "none" } }, + vdom.createElement("input", { class: "toggle-all", type: "checkbox", onChange: ctrl.toggleAll.bind(ctrl) }), + vdom.createElement("ul", { class: "todo-list" }, model.filteredTodos.map(function (todo) { + return vdom.createElement("li", { class: { todo: true, completed: todo.completed, editing: todo == model.editedTodo } }, + vdom.createElement("div", { class: "view" }, (!todo.editable) ? - vdom.createElement("input", {class: "toggle", type: "checkbox"}) - : null, - vdom.createElement("label", {onDoubleClick: function () { ctrl.editTodo(todo); }}, todo.title), - vdom.createElement("button", {class: "destroy", onClick: ctrl.removeTodo.bind(ctrl, todo)}), - vdom.createElement("div", {class: "iconBorder"}, - vdom.createElement("div", {class: "icon"}) - )) - ); + vdom.createElement("input", { class: "toggle", type: "checkbox" }) + : null, + vdom.createElement("label", { onDoubleClick: function () { ctrl.editTodo(todo); } }, todo.title), + vdom.createElement("button", { class: "destroy", onClick: ctrl.removeTodo.bind(ctrl, todo) }), + vdom.createElement("div", { class: "iconBorder" }, + vdom.createElement("div", { class: "icon" })))); })))); }; diff --git a/tests/baselines/reference/tsxReactEmitWhitespace.js b/tests/baselines/reference/tsxReactEmitWhitespace.js index 9a157d242e3..dd69091569f 100644 --- a/tests/baselines/reference/tsxReactEmitWhitespace.js +++ b/tests/baselines/reference/tsxReactEmitWhitespace.js @@ -59,9 +59,9 @@ var p = 0; // Emit " " React.createElement("div", null, " "); // Emit " ", p, " " -React.createElement("div", null, - " ", - p, +React.createElement("div", null, + " ", + p, " "); // Emit only p React.createElement("div", null, p); @@ -76,4 +76,4 @@ React.createElement("div", null, "3"); // Emit no args React.createElement("div", null); // Emit "foo" + ' ' + "bar" -React.createElement("div", null, "foo" + ' ' + "bar"); +React.createElement("div", null, "foo" + " " + "bar"); diff --git a/tests/baselines/reference/tsxReactEmitWhitespace2.js b/tests/baselines/reference/tsxReactEmitWhitespace2.js index 152d869fc03..0ff92b37131 100644 --- a/tests/baselines/reference/tsxReactEmitWhitespace2.js +++ b/tests/baselines/reference/tsxReactEmitWhitespace2.js @@ -18,15 +18,15 @@ declare var React: any; //// [file.js] // Emit ' word' in the last string -React.createElement("div", null, - "word ", - React.createElement("code", null, "code"), +React.createElement("div", null, + "word ", + React.createElement("code", null, "code"), " word"); // Same here -React.createElement("div", null, - React.createElement("code", null, "code"), +React.createElement("div", null, + React.createElement("code", null, "code"), " word"); // And here -React.createElement("div", null, - React.createElement("code", null), +React.createElement("div", null, + React.createElement("code", null), " word"); From e3e45c535426fe1dc5f131c7bfb1287d982d8ad0 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Tue, 5 Apr 2016 17:42:49 -0700 Subject: [PATCH 3/8] Fixes comment emit for down-level accessor declarations. --- src/compiler/factory.ts | 35 +++++++++++++++++++++----------- src/compiler/printer.ts | 12 ++++++++--- src/compiler/transformers/es6.ts | 33 ++++++++++++++++++------------ src/compiler/types.ts | 9 ++++---- 4 files changed, 57 insertions(+), 32 deletions(-) diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 11985e17de8..6fbc4f13037 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -898,22 +898,23 @@ namespace ts { ); } - function createPropertyDescriptor({ get, set, value, enumerable, configurable, writable }: PropertyDescriptorOptions, preferNewLine?: boolean, location?: TextRange) { + function createPropertyDescriptor({ get, set, value, enumerable, configurable, writable }: PropertyDescriptorOptions, preferNewLine?: boolean, location?: TextRange, descriptorLocations?: PropertyDescriptorLocations) { const properties: ObjectLiteralElement[] = []; - addPropertyAssignment(properties, "get", get, preferNewLine); - addPropertyAssignment(properties, "set", set, preferNewLine); - addPropertyAssignment(properties, "value", value, preferNewLine); - addPropertyAssignment(properties, "enumerable", enumerable, preferNewLine); - addPropertyAssignment(properties, "configurable", configurable, preferNewLine); - addPropertyAssignment(properties, "writable", writable, preferNewLine); - return createObjectLiteral(properties, location); + addPropertyAssignment(properties, "get", get, preferNewLine, descriptorLocations); + addPropertyAssignment(properties, "set", set, preferNewLine, descriptorLocations); + addPropertyAssignment(properties, "value", value, preferNewLine, descriptorLocations); + addPropertyAssignment(properties, "enumerable", enumerable, preferNewLine, descriptorLocations); + addPropertyAssignment(properties, "configurable", configurable, preferNewLine, descriptorLocations); + addPropertyAssignment(properties, "writable", writable, preferNewLine, descriptorLocations); + return createObjectLiteral(properties, location, preferNewLine); } - function addPropertyAssignment(properties: ObjectLiteralElement[], name: string, value: boolean | Expression, preferNewLine: boolean) { + function addPropertyAssignment(properties: ObjectLiteralElement[], name: string, value: boolean | Expression, preferNewLine: boolean, descriptorLocations?: PropertyDescriptorLocations) { if (value !== undefined) { const property = createPropertyAssignment( name, - typeof value === "boolean" ? createLiteral(value) : value + typeof value === "boolean" ? createLiteral(value) : value, + descriptorLocations ? descriptorLocations[name] : undefined ); if (preferNewLine) { @@ -933,7 +934,17 @@ namespace ts { writable?: boolean | Expression; } - export function createObjectDefineProperty(target: Expression, memberName: Expression, descriptor: PropertyDescriptorOptions, preferNewLine?: boolean, location?: TextRange) { + export interface PropertyDescriptorLocations { + [key: string]: TextRange; + get?: TextRange; + set?: TextRange; + value?: TextRange; + enumerable?: TextRange; + configurable?: TextRange; + writable?: TextRange; + } + + export function createObjectDefineProperty(target: Expression, memberName: Expression, descriptor: PropertyDescriptorOptions, preferNewLine?: boolean, location?: TextRange, descriptorLocations?: PropertyDescriptorLocations) { return createCall( createPropertyAccess( createIdentifier("Object"), @@ -942,7 +953,7 @@ namespace ts { [ target, memberName, - createPropertyDescriptor(descriptor, preferNewLine) + createPropertyDescriptor(descriptor, preferNewLine, /*location*/ undefined, descriptorLocations) ], location ); diff --git a/src/compiler/printer.ts b/src/compiler/printer.ts index 438fe445109..ab8c2fdccce 100644 --- a/src/compiler/printer.ts +++ b/src/compiler/printer.ts @@ -295,8 +295,8 @@ const _super = (function (geti, seti) { function emitNodeWithWorker(node: Node, emitWorker: (node: Node) => void) { if (node) { - const leadingComments = getLeadingComments(node, isNotEmittedStatement); - const trailingComments = getTrailingComments(node, isNotEmittedStatement); + const leadingComments = getLeadingComments(node, shouldSkipCommentsForNode); + const trailingComments = getTrailingComments(node, shouldSkipCommentsForNode); emitLeadingComments(node, leadingComments); emitStart(node, shouldIgnoreSourceMapForNode, shouldIgnoreSourceMapForChildren); emitWorker(node); @@ -305,6 +305,11 @@ const _super = (function (geti, seti) { } } + function shouldSkipCommentsForNode(node: Node) { + return isNotEmittedStatement(node) + || (getNodeEmitFlags(node) & NodeEmitFlags.NoComments) !== 0; + } + function shouldIgnoreSourceMapForNode(node: Node) { return isNotEmittedOrPartiallyEmittedNode(node) || (getNodeEmitFlags(node) & NodeEmitFlags.NoSourceMap) !== 0; @@ -2307,7 +2312,8 @@ const _super = (function (geti, seti) { if (format & ListFormat.MultiLine) { return true; } - else if (format & ListFormat.PreserveLines) { + + if (format & ListFormat.PreserveLines) { if (format & ListFormat.PreferNewLine) { return true; } diff --git a/src/compiler/transformers/es6.ts b/src/compiler/transformers/es6.ts index 91f5147f941..aba5b209e61 100644 --- a/src/compiler/transformers/es6.ts +++ b/src/compiler/transformers/es6.ts @@ -1094,20 +1094,27 @@ namespace ts { * @param receiver The receiver for the member. */ function transformAccessorsToExpression(receiver: LeftHandSideExpression, { firstAccessor, getAccessor, setAccessor }: AllAccessorDeclarations): Expression { - return createObjectDefineProperty( - receiver, - createExpressionForPropertyName( - visitNode(firstAccessor.name, visitor, isPropertyName), - /*location*/ firstAccessor.name + return setNodeEmitFlags( + createObjectDefineProperty( + receiver, + createExpressionForPropertyName( + visitNode(firstAccessor.name, visitor, isPropertyName), + /*location*/ firstAccessor.name + ), + /*descriptor*/ { + get: getAccessor && transformFunctionLikeToExpression(getAccessor, /*location*/ getAccessor, /*name*/ undefined), + set: setAccessor && transformFunctionLikeToExpression(setAccessor, /*location*/ setAccessor, /*name*/ undefined), + enumerable: true, + configurable: true + }, + /*preferNewLine*/ true, + /*location*/ firstAccessor, + /*descriptorLocations*/ { + get: getAccessor, + set: setAccessor + } ), - { - get: getAccessor && transformFunctionLikeToExpression(getAccessor, /*location*/ getAccessor, /*name*/ undefined), - set: setAccessor && transformFunctionLikeToExpression(setAccessor, /*location*/ setAccessor, /*name*/ undefined), - enumerable: true, - configurable: true - }, - /*preferNewLine*/ true, - /*location*/ firstAccessor + NodeEmitFlags.NoComments ); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index d9d456273b0..ad304ac8150 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2867,14 +2867,15 @@ namespace ts { EmitAdvancedSuperHelper = 1 << 3, // Emit the advanced _super helper for async methods. UMDDefine = 1 << 4, // This node should be replaced with the UMD define helper. NoLexicalEnvironment = 1 << 5, // A new LexicalEnvironment should *not* be introduced when emitting this node, this is primarily used when printing a SystemJS module. - SingleLine = 1 << 6, // The contents of this node should be emit on a single line. - AdviseOnEmitNode = 1 << 7, // The node printer should invoke the onBeforeEmitNode and onAfterEmitNode callbacks when printing this node. + SingleLine = 1 << 6, // The contents of this node should be emitted on a single line. + AdviseOnEmitNode = 1 << 7, // The printer should invoke the onEmitNode callback when printing this node. NoSubstitution = 1 << 8, // Disables further substitution of an expression. CapturesThis = 1 << 9, // The function captures a lexical `this` NoSourceMap = 1 << 10, // Do not emit a source map location for this node. NoNestedSourceMaps = 1 << 11, // Do not emit source map locations for children of this node. - PrefixExportedLocal = 1 << 12, // Ensure an export prefix is added for an identifier that points to an exported declaration with a local name (see SymbolFlags.ExportHasLocal). - Indented = 1 << 13, // Adds an explicit extra indentation level for class and function bodies when printing (used to match old emitter). + NoComments = 1 << 12, // Do not emit comments for this node. + PrefixExportedLocal = 1 << 13, // Ensure an export prefix is added for an identifier that points to an exported declaration with a local name (see SymbolFlags.ExportHasLocal). + Indented = 1 << 14, // Adds an explicit extra indentation level for class and function bodies when printing (used to match old emitter). } /** Additional context provided to `visitEachChild` */ From 8988ea849bf8c031323679fb1a7546bc79551c99 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Tue, 5 Apr 2016 18:24:02 -0700 Subject: [PATCH 4/8] Fixes indentation of object literals with computed properties --- src/compiler/printer.ts | 9 +++++++++ src/compiler/transformers/es6.ts | 11 +++++++---- src/compiler/utilities.ts | 3 +++ .../reference/computedPropertyNames16_ES5.js | 10 ++++++++++ .../reference/computedPropertyNames36_ES5.js | 4 ++++ .../reference/computedPropertyNames37_ES5.js | 4 ++++ .../reference/computedPropertyNames43_ES5.js | 4 ++++ .../reference/computedPropertyNames49_ES5.js | 1 - .../reference/computedPropertyNames50_ES5.js | 1 - 9 files changed, 41 insertions(+), 6 deletions(-) diff --git a/src/compiler/printer.ts b/src/compiler/printer.ts index ab8c2fdccce..c8ddc1c81a7 100644 --- a/src/compiler/printer.ts +++ b/src/compiler/printer.ts @@ -964,9 +964,18 @@ const _super = (function (geti, seti) { write("{}"); } else { + const indentedFlag = getNodeEmitFlags(node) & NodeEmitFlags.Indented; + if (indentedFlag) { + increaseIndent(); + } + const preferNewLine = node.multiLine ? ListFormat.PreferNewLine : ListFormat.None; const allowTrailingComma = languageVersion >= ScriptTarget.ES5 ? ListFormat.AllowTrailingComma : ListFormat.None; emitList(node, properties, ListFormat.ObjectLiteralExpressionProperties | allowTrailingComma | preferNewLine); + + if (indentedFlag) { + decreaseIndent(); + } } } diff --git a/src/compiler/transformers/es6.ts b/src/compiler/transformers/es6.ts index aba5b209e61..648ad7c8eac 100644 --- a/src/compiler/transformers/es6.ts +++ b/src/compiler/transformers/es6.ts @@ -1688,10 +1688,13 @@ namespace ts { addNode(expressions, createAssignment( temp, - createObjectLiteral( - visitNodes(properties, visitor, isObjectLiteralElement, 0, numInitialNonComputedProperties), - /*location*/ undefined, - node.multiLine + setNodeEmitFlags( + createObjectLiteral( + visitNodes(properties, visitor, isObjectLiteralElement, 0, numInitialNonComputedProperties), + /*location*/ undefined, + node.multiLine + ), + NodeEmitFlags.Indented ) ), node.multiLine diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index bbe38798df3..1498f9aa93c 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1637,6 +1637,9 @@ namespace ts { const rightHandSideName = (nameExpression).name.text; return getPropertyNameForKnownSymbolName(rightHandSideName); } + if (isStringOrNumericLiteral(nameExpression.kind)) { + return (nameExpression).text; + } } return undefined; diff --git a/tests/baselines/reference/computedPropertyNames16_ES5.js b/tests/baselines/reference/computedPropertyNames16_ES5.js index 5d8471e6560..92b98ecb1ba 100644 --- a/tests/baselines/reference/computedPropertyNames16_ES5.js +++ b/tests/baselines/reference/computedPropertyNames16_ES5.js @@ -48,6 +48,16 @@ var C = (function () { enumerable: true, configurable: true }); + Object.defineProperty(C, "", { + set: function (v) { }, + enumerable: true, + configurable: true + }); + Object.defineProperty(C.prototype, 0, { + get: function () { return 0; }, + enumerable: true, + configurable: true + }); Object.defineProperty(C.prototype, a, { set: function (v) { }, enumerable: true, diff --git a/tests/baselines/reference/computedPropertyNames36_ES5.js b/tests/baselines/reference/computedPropertyNames36_ES5.js index 884e425e25b..ec5643db26a 100644 --- a/tests/baselines/reference/computedPropertyNames36_ES5.js +++ b/tests/baselines/reference/computedPropertyNames36_ES5.js @@ -27,6 +27,10 @@ var C = (function () { Object.defineProperty(C.prototype, "get1", { // Computed properties get: function () { return new Foo; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(C.prototype, "set1", { set: function (p) { }, enumerable: true, configurable: true diff --git a/tests/baselines/reference/computedPropertyNames37_ES5.js b/tests/baselines/reference/computedPropertyNames37_ES5.js index 8cdc0af30e7..914fd9a898e 100644 --- a/tests/baselines/reference/computedPropertyNames37_ES5.js +++ b/tests/baselines/reference/computedPropertyNames37_ES5.js @@ -27,6 +27,10 @@ var C = (function () { Object.defineProperty(C.prototype, "get1", { // Computed properties get: function () { return new Foo; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(C.prototype, "set1", { set: function (p) { }, enumerable: true, configurable: true diff --git a/tests/baselines/reference/computedPropertyNames43_ES5.js b/tests/baselines/reference/computedPropertyNames43_ES5.js index 9690d0b8196..c79a4d8d6d1 100644 --- a/tests/baselines/reference/computedPropertyNames43_ES5.js +++ b/tests/baselines/reference/computedPropertyNames43_ES5.js @@ -41,6 +41,10 @@ var D = (function (_super) { Object.defineProperty(D.prototype, "get1", { // Computed properties get: function () { return new Foo; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(D.prototype, "set1", { set: function (p) { }, enumerable: true, configurable: true diff --git a/tests/baselines/reference/computedPropertyNames49_ES5.js b/tests/baselines/reference/computedPropertyNames49_ES5.js index 12c3430fbe9..d4eb26a08a5 100644 --- a/tests/baselines/reference/computedPropertyNames49_ES5.js +++ b/tests/baselines/reference/computedPropertyNames49_ES5.js @@ -60,7 +60,6 @@ var x = (_a = { enumerable: true, configurable: true }), - , _a.p2 = 20, _a); var _a; diff --git a/tests/baselines/reference/computedPropertyNames50_ES5.js b/tests/baselines/reference/computedPropertyNames50_ES5.js index db9a03578df..0c6f1798c93 100644 --- a/tests/baselines/reference/computedPropertyNames50_ES5.js +++ b/tests/baselines/reference/computedPropertyNames50_ES5.js @@ -56,7 +56,6 @@ var x = (_a = { enumerable: true, configurable: true }), - , _a.p2 = 20, _a); var _a; From 1c162fa009682347e6f74ad996c784c8c0c39d9f Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Wed, 6 Apr 2016 14:48:26 -0700 Subject: [PATCH 5/8] fix scope tracking when converting loops --- src/compiler/transformers/es6.ts | 2 +- tests/baselines/reference/nestedBlockScopedBindings13.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/transformers/es6.ts b/src/compiler/transformers/es6.ts index 648ad7c8eac..41d74d9b60a 100644 --- a/src/compiler/transformers/es6.ts +++ b/src/compiler/transformers/es6.ts @@ -1796,7 +1796,7 @@ namespace ts { } } - let loopBody = visitEachChild(node.statement, visitor, context); + let loopBody = visitNode(node.statement, visitor, isStatement); const currentState = convertedLoopState; convertedLoopState = outerConvertedLoopState; diff --git a/tests/baselines/reference/nestedBlockScopedBindings13.js b/tests/baselines/reference/nestedBlockScopedBindings13.js index 86e5635df68..6100e24ac09 100644 --- a/tests/baselines/reference/nestedBlockScopedBindings13.js +++ b/tests/baselines/reference/nestedBlockScopedBindings13.js @@ -10,7 +10,7 @@ for (; false;) { } //// [nestedBlockScopedBindings13.js] -var _loop_1 = function() { +var _loop_1 = function () { var x; (function () { return x; }); }; From 4da09b73bc4e84efdf1017481c30b8e427172f38 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Wed, 6 Apr 2016 15:49:53 -0700 Subject: [PATCH 6/8] Fixes extra parens around yield downleveled from await --- src/compiler/factory.ts | 14 +++++++++++--- src/compiler/transformers/ts.ts | 2 +- .../reference/FunctionDeclaration10_es6.js | 2 +- tests/baselines/reference/classExpressionES63.js | 8 ++++---- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 6fbc4f13037..573679b4f1a 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -1272,10 +1272,19 @@ namespace ts { // If `a ** d` is on the left of operator `**`, we need to parenthesize to preserve // the intended order of operations: `(a ** b) ** c` const binaryOperatorPrecedence = getOperatorPrecedence(SyntaxKind.BinaryExpression, binaryOperator); + const binaryOperatorAssociativity = getOperatorAssociativity(SyntaxKind.BinaryExpression, binaryOperator); const emittedOperand = skipPartiallyEmittedExpressions(operand); const operandPrecedence = getExpressionPrecedence(emittedOperand); switch (compareValues(operandPrecedence, binaryOperatorPrecedence)) { case Comparison.LessThan: + // If the operand is the right side of a right-associative binary operation + // and is a yield expression, then we do not need parentheses. + if (!isLeftSideOfBinary + && binaryOperatorAssociativity === Associativity.Right + && operand.kind === SyntaxKind.YieldExpression) { + return false; + } + return true; case Comparison.GreaterThan: @@ -1287,12 +1296,11 @@ namespace ts { // left associative: // (a*b)/x -> a*b/x // (a**b)/x -> a**b/x - + // // Parentheses are needed for the left operand when the binary operator is // right associative: // (a/b)**x -> (a/b)**x // (a**b)**x -> (a**b)**x - const binaryOperatorAssociativity = getOperatorAssociativity(SyntaxKind.BinaryExpression, binaryOperator); return binaryOperatorAssociativity === Associativity.Right; } else { @@ -1326,7 +1334,7 @@ namespace ts { // associative: // x/(a**b) -> x/a**b // x**(a**b) -> x**a**b - + // // Parentheses are needed for the right operand when the operand is left // associative: // x/(a*b) -> x/(a*b) diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 182ea518d30..1d8dd46edee 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -748,7 +748,7 @@ namespace ts { function transformConstructorParameters(constructor: ConstructorDeclaration, hasExtendsClause: boolean) { return constructor ? visitNodes(constructor.parameters, visitor, isParameter) - : hasExtendsClause ? [createRestParameter(createUniqueName("args"))] : []; + : hasExtendsClause ? [createRestParameter("args")] : []; } /** diff --git a/tests/baselines/reference/FunctionDeclaration10_es6.js b/tests/baselines/reference/FunctionDeclaration10_es6.js index 79a1740b17e..6ac2ec8d194 100644 --- a/tests/baselines/reference/FunctionDeclaration10_es6.js +++ b/tests/baselines/reference/FunctionDeclaration10_es6.js @@ -4,7 +4,7 @@ function * foo(a = yield => yield) { //// [FunctionDeclaration10_es6.js] function* foo(a) { - if (a === void 0) { a = (yield); } + if (a === void 0) { a = yield; } } yield; { diff --git a/tests/baselines/reference/classExpressionES63.js b/tests/baselines/reference/classExpressionES63.js index 7bb41817079..254014c9458 100644 --- a/tests/baselines/reference/classExpressionES63.js +++ b/tests/baselines/reference/classExpressionES63.js @@ -12,13 +12,13 @@ let C = class extends class extends class { this.a = 1; } } { - constructor(...args_1) { - super(...args_1); + constructor(...args) { + super(...args); this.b = 2; } } { - constructor(...args_2) { - super(...args_2); + constructor(...args) { + super(...args); this.c = 3; } }; From dfdfec9efa82a109c749c3ade4854d60e659ee2e Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Wed, 6 Apr 2016 15:54:50 -0700 Subject: [PATCH 7/8] treat classes as block scoped entities --- src/compiler/transformers/es6.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/compiler/transformers/es6.ts b/src/compiler/transformers/es6.ts index 648ad7c8eac..566f6dde846 100644 --- a/src/compiler/transformers/es6.ts +++ b/src/compiler/transformers/es6.ts @@ -606,6 +606,9 @@ namespace ts { // return C; // }(D)) + if (node.name) { + enableSubstitutionsForBlockScopedBindings(); + } const baseTypeNode = getClassExtendsHeritageClauseElement(node); const classFunction = createFunctionExpression( /*asteriskToken*/ undefined, From 3daeba3b539e06f7862ad341a9b3c049dc504225 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Wed, 6 Apr 2016 16:33:34 -0700 Subject: [PATCH 8/8] Fix literal property names --- src/compiler/factory.ts | 12 +++++++++--- src/compiler/transformers/ts.ts | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 573679b4f1a..f7aa18fa7ea 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -711,9 +711,15 @@ namespace ts { } export function createMemberAccessForPropertyName(target: Expression, memberName: PropertyName, location?: TextRange): MemberExpression { - return isIdentifier(memberName) - ? createPropertyAccess(target, getSynthesizedClone(memberName), location) - : createElementAccess(target, getSynthesizedClone(isComputedPropertyName(memberName) ? memberName.expression : memberName), location); + if (isIdentifier(memberName)) { + return createPropertyAccess(target, getSynthesizedClone(memberName), location); + } + else if (isComputedPropertyName(memberName)) { + return createElementAccess(target, memberName.expression, location); + } + else { + return createElementAccess(target, memberName, location); + } } export function createRestParameter(name: string | Identifier) { diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 1d8dd46edee..bcf79b91532 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -1749,7 +1749,7 @@ namespace ts { ); } else { - return getSynthesizedClone(name); + return name; } }