Declaration emit spread types and downlevel spread

This commit is contained in:
Nathan Shively-Sanders 2016-09-26 09:31:34 -07:00
parent a3ffe6f874
commit 7004652a0a
5 changed files with 95 additions and 4 deletions

View File

@ -1121,6 +1121,14 @@ namespace ts {
writeLine();
}
function emitSpreadTypeElement(type: SpreadTypeElement) {
write("...");
emitType(type.type);
write(";");
writeLine();
}
function emitVariableDeclaration(node: VariableDeclaration) {
// If we are emitting property it isn't moduleElement and hence we already know it needs to be emitted
// so there is no check needed to see if declaration is visible
@ -1702,6 +1710,8 @@ namespace ts {
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.PropertySignature:
return emitPropertyDeclaration(<PropertyDeclaration>node);
case SyntaxKind.SpreadTypeElement:
return emitSpreadTypeElement(node as SpreadTypeElement);
case SyntaxKind.EnumMember:
return emitEnumMemberDeclaration(<EnumMember>node);
case SyntaxKind.ExportAssignment:

View File

@ -2195,7 +2195,7 @@ const _super = (function (geti, seti) {
helpersEmitted = true;
}
if (compilerOptions.jsx !== JsxEmit.Preserve && !assignEmitted && (node.flags & NodeFlags.HasJsxSpreadAttributes)) {
if (compilerOptions.jsx !== JsxEmit.Preserve && !assignEmitted && (node.flags & NodeFlags.HasSpreadAttribute)) {
writeLines(assignHelper);
assignEmitted = true;
}

View File

@ -1,6 +1,7 @@
/// <reference path="visitor.ts" />
/// <reference path="transformers/ts.ts" />
/// <reference path="transformers/jsx.ts" />
/// <reference path="transformers/experimental.ts" />
/// <reference path="transformers/es7.ts" />
/// <reference path="transformers/es6.ts" />
/// <reference path="transformers/generators.ts" />
@ -176,6 +177,7 @@ namespace ts {
transformers.push(transformJsx);
}
transformers.push(transformExperimental);
transformers.push(transformES7);
if (languageVersion < ScriptTarget.ES6) {
@ -629,4 +631,4 @@ namespace ts {
return t => t;
}
}
}
}

View File

@ -28,7 +28,6 @@ namespace ts {
switch (node.kind) {
case SyntaxKind.BinaryExpression:
return visitBinaryExpression(<BinaryExpression>node);
default:
Debug.failBadSyntaxKind(node);
return visitEachChild(node, visitor, context);
@ -94,4 +93,4 @@ namespace ts {
}
}
}
}
}

View File

@ -0,0 +1,80 @@
/// <reference path="../factory.ts" />
/// <reference path="../visitor.ts" />
/*@internal*/
namespace ts {
export function transformExperimental(context: TransformationContext) {
return transformSourceFile;
function transformSourceFile(node: SourceFile) {
return visitEachChild(node, visitor, context);
}
function visitor(node: Node): VisitResult<Node> {
if (node.transformFlags & TransformFlags.Experimental) {
return visitorWorker(node);
}
else if (node.transformFlags & TransformFlags.ContainsExperimental) {
return visitEachChild(node, visitor, context);
}
else {
return node;
}
}
function visitorWorker(node: Node): VisitResult<Node> {
switch (node.kind) {
case SyntaxKind.ObjectLiteralExpression:
return visitObjectLiteralExpression(node as ObjectLiteralExpression);
default:
Debug.failBadSyntaxKind(node);
return visitEachChild(node, visitor, context);
}
}
function chunkObjectLiteralElements(elements: ObjectLiteralElement[]): Expression[] {
let chunkObject: (ShorthandPropertyAssignment | PropertyAssignment)[];
const objects: Expression[] = [];
for (const e of elements) {
if (e.kind === SyntaxKind.SpreadElement) {
if (chunkObject) {
objects.push(createObjectLiteral(chunkObject));
chunkObject = undefined;
}
const target = (e as SpreadElement).target;
objects.push(visitNode(target, visitor, isExpression));
}
else {
if (!chunkObject) {
chunkObject = [];
}
if (e.kind === SyntaxKind.PropertyAssignment) {
const p = e as PropertyAssignment;
chunkObject.push(createPropertyAssignment(p.name, visitNode(p.initializer, visitor, isExpression)));
}
else {
chunkObject.push(e as ShorthandPropertyAssignment);
}
}
}
if (chunkObject) {
objects.push(createObjectLiteral(chunkObject));
}
return objects;
}
function visitObjectLiteralExpression(node: ObjectLiteralExpression): Expression {
// spread elements emit like so:
// non-spread elements are chunked together into object literals, and then all are passed to __assign:
// { a, ...o, b } => __assign({a}, o, {b});
// If the first element is a spread element, then the first argument to __assign is {}:
// { ...o, a, b, ...o2 } => __assign({}, o, {a, b}, o2)
const objects = chunkObjectLiteralElements(node.properties);
if (objects.length && objects[0].kind !== SyntaxKind.ObjectLiteralExpression) {
objects.unshift(createObjectLiteral());
}
return createCall(createIdentifier("__assign"), undefined, objects);
}
}
}