mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-22 22:55:36 -05:00
Move emit helpers into related transformers
This commit is contained in:
@@ -19034,7 +19034,7 @@ namespace ts {
|
||||
|
||||
function isNameOfModuleOrEnumDeclaration(node: Identifier) {
|
||||
const parent = node.parent;
|
||||
return isModuleOrEnumDeclaration(parent) && node === parent.name;
|
||||
return parent && isModuleOrEnumDeclaration(parent) && node === parent.name;
|
||||
}
|
||||
|
||||
// When resolved as an expression identifier, if the given node references an exported entity, return the declaration
|
||||
|
||||
@@ -538,7 +538,7 @@ namespace ts {
|
||||
*/
|
||||
export function append<T>(to: T[] | undefined, value: T | undefined): T[] | undefined {
|
||||
if (value === undefined) return to;
|
||||
if (to === undefined) to = [];
|
||||
if (to === undefined) return [value];
|
||||
to.push(value);
|
||||
return to;
|
||||
}
|
||||
@@ -559,6 +559,16 @@ namespace ts {
|
||||
return to;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stable sort of an array. Elements equal to each other maintain their relative position in the array.
|
||||
*/
|
||||
export function stableSort<T>(array: T[], comparer: (x: T, y: T) => Comparison = compareValues) {
|
||||
return array
|
||||
.map((_, i) => i) // create array of indices
|
||||
.sort((x, y) => comparer(array[x], array[y]) || compareValues(x, y)) // sort indices by value then position
|
||||
.map(i => array[i]); // get sorted array
|
||||
}
|
||||
|
||||
export function rangeEquals<T>(array1: T[], array2: T[], pos: number, end: number) {
|
||||
while (pos < end) {
|
||||
if (array1[pos] !== array2[pos]) {
|
||||
@@ -2022,6 +2032,17 @@ namespace ts {
|
||||
}
|
||||
|
||||
/** Remove an item from an array, moving everything to its right one space left. */
|
||||
export function orderedRemoveItem<T>(array: T[], item: T): boolean {
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
if (array[i] === item) {
|
||||
orderedRemoveItemAt(array, i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Remove an item by index from an array, moving everything to its right one space left. */
|
||||
export function orderedRemoveItemAt<T>(array: T[], index: number): void {
|
||||
// This seems to be faster than either `array.splice(i, 1)` or `array.copyWithin(i, i+ 1)`.
|
||||
for (let i = index; i < array.length - 1; i++) {
|
||||
|
||||
@@ -21,153 +21,6 @@ namespace ts {
|
||||
const delimiters = createDelimiterMap();
|
||||
const brackets = createBracketsMap();
|
||||
|
||||
// emit output for the __extends helper function
|
||||
const extendsHelper = `
|
||||
var __extends = (this && this.__extends) || function (d, b) {
|
||||
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};`;
|
||||
|
||||
// Emit output for the __assign helper function.
|
||||
// This is typically used for JSX spread attributes,
|
||||
// and can be used for object literal spread properties.
|
||||
const assignHelper = `
|
||||
var __assign = (this && this.__assign) || Object.assign || function(t) {
|
||||
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
||||
s = arguments[i];
|
||||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
||||
t[p] = s[p];
|
||||
}
|
||||
return t;
|
||||
};`;
|
||||
|
||||
// emit output for the __decorate helper function
|
||||
const decorateHelper = `
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};`;
|
||||
|
||||
// emit output for the __metadata helper function
|
||||
const metadataHelper = `
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};`;
|
||||
|
||||
// emit output for the __param helper function
|
||||
const paramHelper = `
|
||||
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
||||
return function (target, key) { decorator(target, key, paramIndex); }
|
||||
};`;
|
||||
|
||||
// emit output for the __awaiter helper function
|
||||
const awaiterHelper = `
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments)).next());
|
||||
});
|
||||
};`;
|
||||
|
||||
// The __generator helper is used by down-level transformations to emulate the runtime
|
||||
// semantics of an ES2015 generator function. When called, this helper returns an
|
||||
// object that implements the Iterator protocol, in that it has `next`, `return`, and
|
||||
// `throw` methods that step through the generator when invoked.
|
||||
//
|
||||
// parameters:
|
||||
// thisArg The value to use as the `this` binding for the transformed generator body.
|
||||
// body A function that acts as the transformed generator body.
|
||||
//
|
||||
// variables:
|
||||
// _ Persistent state for the generator that is shared between the helper and the
|
||||
// generator body. The state object has the following members:
|
||||
// sent() - A method that returns or throws the current completion value.
|
||||
// label - The next point at which to resume evaluation of the generator body.
|
||||
// trys - A stack of protected regions (try/catch/finally blocks).
|
||||
// ops - A stack of pending instructions when inside of a finally block.
|
||||
// f A value indicating whether the generator is executing.
|
||||
// y An iterator to delegate for a yield*.
|
||||
// t A temporary variable that holds one of the following values (note that these
|
||||
// cases do not overlap):
|
||||
// - The completion value when resuming from a `yield` or `yield*`.
|
||||
// - The error value for a catch block.
|
||||
// - The current protected region (array of try/catch/finally/end labels).
|
||||
// - The verb (`next`, `throw`, or `return` method) to delegate to the expression
|
||||
// of a `yield*`.
|
||||
// - The result of evaluating the verb delegated to the expression of a `yield*`.
|
||||
//
|
||||
// functions:
|
||||
// verb(n) Creates a bound callback to the `step` function for opcode `n`.
|
||||
// step(op) Evaluates opcodes in a generator body until execution is suspended or
|
||||
// completed.
|
||||
//
|
||||
// The __generator helper understands a limited set of instructions:
|
||||
// 0: next(value?) - Start or resume the generator with the specified value.
|
||||
// 1: throw(error) - Resume the generator with an exception. If the generator is
|
||||
// suspended inside of one or more protected regions, evaluates
|
||||
// any intervening finally blocks between the current label and
|
||||
// the nearest catch block or function boundary. If uncaught, the
|
||||
// exception is thrown to the caller.
|
||||
// 2: return(value?) - Resume the generator as if with a return. If the generator is
|
||||
// suspended inside of one or more protected regions, evaluates any
|
||||
// intervening finally blocks.
|
||||
// 3: break(label) - Jump to the specified label. If the label is outside of the
|
||||
// current protected region, evaluates any intervening finally
|
||||
// blocks.
|
||||
// 4: yield(value?) - Yield execution to the caller with an optional value. When
|
||||
// resumed, the generator will continue at the next label.
|
||||
// 5: yield*(value) - Delegates evaluation to the supplied iterator. When
|
||||
// delegation completes, the generator will continue at the next
|
||||
// label.
|
||||
// 6: catch(error) - Handles an exception thrown from within the generator body. If
|
||||
// the current label is inside of one or more protected regions,
|
||||
// evaluates any intervening finally blocks between the current
|
||||
// label and the nearest catch block or function boundary. If
|
||||
// uncaught, the exception is thrown to the caller.
|
||||
// 7: endfinally - Ends a finally block, resuming the last instruction prior to
|
||||
// entering a finally block.
|
||||
//
|
||||
// For examples of how these are used, see the comments in ./transformers/generators.ts
|
||||
const generatorHelper = `
|
||||
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t;
|
||||
return { next: verb(0), "throw": verb(1), "return": verb(2) };
|
||||
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||
function step(op) {
|
||||
if (f) throw new TypeError("Generator is already executing.");
|
||||
while (_) try {
|
||||
if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t;
|
||||
if (y = 0, t) op = [0, t.value];
|
||||
switch (op[0]) {
|
||||
case 0: case 1: t = op; break;
|
||||
case 4: _.label++; return { value: op[1], done: false };
|
||||
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||
default:
|
||||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||
if (t[2]) _.ops.pop();
|
||||
_.trys.pop(); continue;
|
||||
}
|
||||
op = body.call(thisArg, _);
|
||||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||
}
|
||||
};`;
|
||||
|
||||
// emit output for the __export helper function
|
||||
const exportStarHelper = `
|
||||
function __export(m) {
|
||||
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
|
||||
}`;
|
||||
|
||||
// emit output for the UMD helper function.
|
||||
const umdHelper = `
|
||||
(function (dependencies, factory) {
|
||||
@@ -179,15 +32,6 @@ function __export(m) {
|
||||
}
|
||||
})`;
|
||||
|
||||
const superHelper = `
|
||||
const _super = name => super[name];`;
|
||||
|
||||
const advancedSuperHelper = `
|
||||
const _super = (function (geti, seti) {
|
||||
const cache = Object.create(null);
|
||||
return name => cache[name] || (cache[name] = { get value() { return geti(name); }, set value(v) { seti(name, v); } });
|
||||
})(name => super[name], (name, value) => super[name] = value);`;
|
||||
|
||||
const compilerOptions = host.getCompilerOptions();
|
||||
const languageVersion = getEmitScriptTarget(compilerOptions);
|
||||
const moduleKind = getEmitModuleKind(compilerOptions);
|
||||
@@ -224,11 +68,7 @@ const _super = (function (geti, seti) {
|
||||
let currentSourceFile: SourceFile;
|
||||
let currentText: string;
|
||||
let currentFileIdentifiers: Map<string>;
|
||||
let extendsEmitted: boolean;
|
||||
let assignEmitted: boolean;
|
||||
let decorateEmitted: boolean;
|
||||
let paramEmitted: boolean;
|
||||
let awaiterEmitted: boolean;
|
||||
let bundledHelpers: Map<boolean>;
|
||||
let isOwnFileEmit: boolean;
|
||||
let emitSkipped = false;
|
||||
|
||||
@@ -293,12 +133,13 @@ const _super = (function (geti, seti) {
|
||||
nodeIdToGeneratedName = [];
|
||||
autoGeneratedIdToGeneratedName = [];
|
||||
generatedNameSet = createMap<string>();
|
||||
bundledHelpers = isBundledEmit ? createMap<boolean>() : undefined;
|
||||
isOwnFileEmit = !isBundledEmit;
|
||||
|
||||
// Emit helpers from all the files
|
||||
if (isBundledEmit && moduleKind) {
|
||||
for (const sourceFile of sourceFiles) {
|
||||
emitEmitHelpers(sourceFile);
|
||||
emitHelpers(sourceFile, /*isBundle*/ true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -333,11 +174,6 @@ const _super = (function (geti, seti) {
|
||||
tempFlags = TempFlags.Auto;
|
||||
currentSourceFile = undefined;
|
||||
currentText = undefined;
|
||||
extendsEmitted = false;
|
||||
assignEmitted = false;
|
||||
decorateEmitted = false;
|
||||
paramEmitted = false;
|
||||
awaiterEmitted = false;
|
||||
isOwnFileEmit = false;
|
||||
}
|
||||
|
||||
@@ -2141,85 +1977,39 @@ const _super = (function (geti, seti) {
|
||||
return statements.length;
|
||||
}
|
||||
|
||||
function emitHelpers(node: Node) {
|
||||
const emitFlags = getEmitFlags(node);
|
||||
let helpersEmitted = false;
|
||||
if (emitFlags & EmitFlags.EmitEmitHelpers) {
|
||||
helpersEmitted = emitEmitHelpers(currentSourceFile);
|
||||
}
|
||||
|
||||
if (emitFlags & EmitFlags.EmitExportStar) {
|
||||
writeLines(exportStarHelper);
|
||||
helpersEmitted = true;
|
||||
}
|
||||
|
||||
if (emitFlags & EmitFlags.EmitSuperHelper) {
|
||||
writeLines(superHelper);
|
||||
helpersEmitted = true;
|
||||
}
|
||||
|
||||
if (emitFlags & EmitFlags.EmitAdvancedSuperHelper) {
|
||||
writeLines(advancedSuperHelper);
|
||||
helpersEmitted = true;
|
||||
}
|
||||
|
||||
return helpersEmitted;
|
||||
}
|
||||
|
||||
function emitEmitHelpers(node: SourceFile) {
|
||||
// Only emit helpers if the user did not say otherwise.
|
||||
if (compilerOptions.noEmitHelpers) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't emit helpers if we can import them.
|
||||
if (compilerOptions.importHelpers
|
||||
&& (isExternalModule(node) || compilerOptions.isolatedModules)) {
|
||||
return false;
|
||||
}
|
||||
function emitHelpers(node: Node, isBundle?: boolean) {
|
||||
const sourceFile = isSourceFile(node) ? node : currentSourceFile;
|
||||
const shouldSkip = compilerOptions.noEmitHelpers || (sourceFile && getExternalHelpersModuleName(sourceFile) !== undefined);
|
||||
const shouldBundle = isSourceFile(node) && !isOwnFileEmit;
|
||||
|
||||
let helpersEmitted = false;
|
||||
const helpers = getEmitHelpers(node);
|
||||
if (helpers) {
|
||||
for (const helper of stableSort(helpers, compareEmitHelpers)) {
|
||||
if (!helper.scoped) {
|
||||
// Skip the helper if it can be skipped and the noEmitHelpers compiler
|
||||
// option is set, or if it can be imported and the importHelpers compiler
|
||||
// option is set.
|
||||
if (shouldSkip) continue;
|
||||
|
||||
// Only Emit __extends function when target ES5.
|
||||
// For target ES6 and above, we can emit classDeclaration as is.
|
||||
if ((languageVersion < ScriptTarget.ES2015) && (!extendsEmitted && node.flags & NodeFlags.HasClassExtends)) {
|
||||
writeLines(extendsHelper);
|
||||
extendsEmitted = true;
|
||||
helpersEmitted = true;
|
||||
}
|
||||
// Skip the helper if it can be bundled but hasn't already been emitted and we
|
||||
// are emitting a bundled module.
|
||||
if (shouldBundle) {
|
||||
if (helper.name in bundledHelpers) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (compilerOptions.jsx !== JsxEmit.Preserve && !assignEmitted && (node.flags & NodeFlags.HasJsxSpreadAttributes)) {
|
||||
writeLines(assignHelper);
|
||||
assignEmitted = true;
|
||||
}
|
||||
bundledHelpers[helper.name] = true;
|
||||
}
|
||||
}
|
||||
else if (isBundle) {
|
||||
// Skip the helper if it is scoped and we are emitting bundled helpers
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!decorateEmitted && node.flags & NodeFlags.HasDecorators) {
|
||||
writeLines(decorateHelper);
|
||||
if (compilerOptions.emitDecoratorMetadata) {
|
||||
writeLines(metadataHelper);
|
||||
writeLines(helper.text);
|
||||
helpersEmitted = true;
|
||||
}
|
||||
|
||||
decorateEmitted = true;
|
||||
helpersEmitted = true;
|
||||
}
|
||||
|
||||
if (!paramEmitted && node.flags & NodeFlags.HasParamDecorators) {
|
||||
writeLines(paramHelper);
|
||||
paramEmitted = true;
|
||||
helpersEmitted = true;
|
||||
}
|
||||
|
||||
// Only emit __awaiter function when target ES5/ES6.
|
||||
// Only emit __generator function when target ES5.
|
||||
// For target ES2017 and above, we can emit async/await as is.
|
||||
if ((languageVersion < ScriptTarget.ES2017) && (!awaiterEmitted && node.flags & NodeFlags.HasAsyncFunctions)) {
|
||||
writeLines(awaiterHelper);
|
||||
if (languageVersion < ScriptTarget.ES2015) {
|
||||
writeLines(generatorHelper);
|
||||
}
|
||||
|
||||
awaiterEmitted = true;
|
||||
helpersEmitted = true;
|
||||
}
|
||||
|
||||
if (helpersEmitted) {
|
||||
@@ -2230,9 +2020,10 @@ const _super = (function (geti, seti) {
|
||||
}
|
||||
|
||||
function writeLines(text: string): void {
|
||||
const lines = text.split(/\r\n|\r|\n/g);
|
||||
const lines = text.split(/\r\n?|\n/g);
|
||||
const indentation = guessIndentation(lines);
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const line = lines[i];
|
||||
const line = indentation ? lines[i].slice(indentation) : lines[i];
|
||||
if (line.length) {
|
||||
if (i > 0) {
|
||||
writeLine();
|
||||
@@ -2242,6 +2033,21 @@ const _super = (function (geti, seti) {
|
||||
}
|
||||
}
|
||||
|
||||
function guessIndentation(lines: string[]) {
|
||||
let indentation: number;
|
||||
for (const line of lines) {
|
||||
for (let i = 0; i < line.length && (indentation === undefined || i < indentation); i++) {
|
||||
if (!isWhiteSpace(line.charCodeAt(i))) {
|
||||
if (indentation === undefined || i < indentation) {
|
||||
indentation = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return indentation;
|
||||
}
|
||||
|
||||
//
|
||||
// Helpers
|
||||
//
|
||||
|
||||
@@ -1440,7 +1440,6 @@ namespace ts {
|
||||
if (node.resolvedTypeReferenceDirectiveNames !== undefined) updated.resolvedTypeReferenceDirectiveNames = node.resolvedTypeReferenceDirectiveNames;
|
||||
if (node.imports !== undefined) updated.imports = node.imports;
|
||||
if (node.moduleAugmentations !== undefined) updated.moduleAugmentations = node.moduleAugmentations;
|
||||
if (node.externalHelpersModuleName !== undefined) updated.externalHelpersModuleName = node.externalHelpersModuleName;
|
||||
return updateNode(updated, node);
|
||||
}
|
||||
|
||||
@@ -1683,278 +1682,23 @@ namespace ts {
|
||||
|
||||
// Helpers
|
||||
|
||||
export function createHelperName(externalHelpersModuleName: Identifier | undefined, name: string) {
|
||||
export interface EmitHelperState {
|
||||
currentSourceFile: SourceFile;
|
||||
compilerOptions: CompilerOptions;
|
||||
requestedHelpers?: EmitHelper[];
|
||||
}
|
||||
|
||||
export function getHelperName(helperState: EmitHelperState, name: string) {
|
||||
const externalHelpersModuleName = getOrCreateExternalHelpersModuleName(helperState.currentSourceFile, helperState.compilerOptions);
|
||||
return externalHelpersModuleName
|
||||
? createPropertyAccess(externalHelpersModuleName, name)
|
||||
: createIdentifier(name);
|
||||
}
|
||||
|
||||
export function createExtendsHelper(externalHelpersModuleName: Identifier | undefined, name: Identifier) {
|
||||
return createCall(
|
||||
createHelperName(externalHelpersModuleName, "__extends"),
|
||||
/*typeArguments*/ undefined,
|
||||
[
|
||||
name,
|
||||
createIdentifier("_super")
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
export function createAssignHelper(externalHelpersModuleName: Identifier | undefined, attributesSegments: Expression[]) {
|
||||
return createCall(
|
||||
createHelperName(externalHelpersModuleName, "__assign"),
|
||||
/*typeArguments*/ undefined,
|
||||
attributesSegments
|
||||
);
|
||||
}
|
||||
|
||||
export function createParamHelper(externalHelpersModuleName: Identifier | undefined, expression: Expression, parameterOffset: number, location?: TextRange) {
|
||||
return createCall(
|
||||
createHelperName(externalHelpersModuleName, "__param"),
|
||||
/*typeArguments*/ undefined,
|
||||
[
|
||||
createLiteral(parameterOffset),
|
||||
expression
|
||||
],
|
||||
location
|
||||
);
|
||||
}
|
||||
|
||||
export function createMetadataHelper(externalHelpersModuleName: Identifier | undefined, metadataKey: string, metadataValue: Expression) {
|
||||
return createCall(
|
||||
createHelperName(externalHelpersModuleName, "__metadata"),
|
||||
/*typeArguments*/ undefined,
|
||||
[
|
||||
createLiteral(metadataKey),
|
||||
metadataValue
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
export function createDecorateHelper(externalHelpersModuleName: Identifier | undefined, decoratorExpressions: Expression[], target: Expression, memberName?: Expression, descriptor?: Expression, location?: TextRange) {
|
||||
const argumentsArray: Expression[] = [];
|
||||
argumentsArray.push(createArrayLiteral(decoratorExpressions, /*location*/ undefined, /*multiLine*/ true));
|
||||
argumentsArray.push(target);
|
||||
if (memberName) {
|
||||
argumentsArray.push(memberName);
|
||||
if (descriptor) {
|
||||
argumentsArray.push(descriptor);
|
||||
}
|
||||
export function requestEmitHelper(helperState: EmitHelperState, helper: EmitHelper) {
|
||||
if (!contains(helperState.requestedHelpers, helper)) {
|
||||
helperState.requestedHelpers = append(helperState.requestedHelpers, helper);
|
||||
}
|
||||
|
||||
return createCall(createHelperName(externalHelpersModuleName, "__decorate"), /*typeArguments*/ undefined, argumentsArray, location);
|
||||
}
|
||||
|
||||
export function createAwaiterHelper(externalHelpersModuleName: Identifier | undefined, hasLexicalArguments: boolean, promiseConstructor: EntityName | Expression, body: Block) {
|
||||
const generatorFunc = createFunctionExpression(
|
||||
/*modifiers*/ undefined,
|
||||
createToken(SyntaxKind.AsteriskToken),
|
||||
/*name*/ undefined,
|
||||
/*typeParameters*/ undefined,
|
||||
/*parameters*/ [],
|
||||
/*type*/ undefined,
|
||||
body
|
||||
);
|
||||
|
||||
// Mark this node as originally an async function
|
||||
(generatorFunc.emitNode || (generatorFunc.emitNode = {})).flags |= EmitFlags.AsyncFunctionBody;
|
||||
|
||||
return createCall(
|
||||
createHelperName(externalHelpersModuleName, "__awaiter"),
|
||||
/*typeArguments*/ undefined,
|
||||
[
|
||||
createThis(),
|
||||
hasLexicalArguments ? createIdentifier("arguments") : createVoidZero(),
|
||||
promiseConstructor ? createExpressionFromEntityName(promiseConstructor) : createVoidZero(),
|
||||
generatorFunc
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
export function createHasOwnProperty(target: LeftHandSideExpression, propertyName: Expression) {
|
||||
return createCall(
|
||||
createPropertyAccess(target, "hasOwnProperty"),
|
||||
/*typeArguments*/ undefined,
|
||||
[propertyName]
|
||||
);
|
||||
}
|
||||
|
||||
function createObjectCreate(prototype: Expression) {
|
||||
return createCall(
|
||||
createPropertyAccess(createIdentifier("Object"), "create"),
|
||||
/*typeArguments*/ undefined,
|
||||
[prototype]
|
||||
);
|
||||
}
|
||||
|
||||
function createGeti(target: LeftHandSideExpression) {
|
||||
// name => super[name]
|
||||
return createArrowFunction(
|
||||
/*modifiers*/ undefined,
|
||||
/*typeParameters*/ undefined,
|
||||
[createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "name")],
|
||||
/*type*/ undefined,
|
||||
createToken(SyntaxKind.EqualsGreaterThanToken),
|
||||
createElementAccess(target, createIdentifier("name"))
|
||||
);
|
||||
}
|
||||
|
||||
function createSeti(target: LeftHandSideExpression) {
|
||||
// (name, value) => super[name] = value
|
||||
return createArrowFunction(
|
||||
/*modifiers*/ undefined,
|
||||
/*typeParameters*/ undefined,
|
||||
[
|
||||
createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "name"),
|
||||
createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "value")
|
||||
],
|
||||
/*type*/ undefined,
|
||||
createToken(SyntaxKind.EqualsGreaterThanToken),
|
||||
createAssignment(
|
||||
createElementAccess(
|
||||
target,
|
||||
createIdentifier("name")
|
||||
),
|
||||
createIdentifier("value")
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export function createAdvancedAsyncSuperHelper() {
|
||||
// const _super = (function (geti, seti) {
|
||||
// const cache = Object.create(null);
|
||||
// return name => cache[name] || (cache[name] = { get value() { return geti(name); }, set value(v) { seti(name, v); } });
|
||||
// })(name => super[name], (name, value) => super[name] = value);
|
||||
|
||||
// const cache = Object.create(null);
|
||||
const createCache = createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
createConstDeclarationList([
|
||||
createVariableDeclaration(
|
||||
"cache",
|
||||
/*type*/ undefined,
|
||||
createObjectCreate(createNull())
|
||||
)
|
||||
])
|
||||
);
|
||||
|
||||
// get value() { return geti(name); }
|
||||
const getter = createGetAccessor(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
"value",
|
||||
/*parameters*/ [],
|
||||
/*type*/ undefined,
|
||||
createBlock([
|
||||
createReturn(
|
||||
createCall(
|
||||
createIdentifier("geti"),
|
||||
/*typeArguments*/ undefined,
|
||||
[createIdentifier("name")]
|
||||
)
|
||||
)
|
||||
])
|
||||
);
|
||||
|
||||
// set value(v) { seti(name, v); }
|
||||
const setter = createSetAccessor(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
"value",
|
||||
[createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "v")],
|
||||
createBlock([
|
||||
createStatement(
|
||||
createCall(
|
||||
createIdentifier("seti"),
|
||||
/*typeArguments*/ undefined,
|
||||
[
|
||||
createIdentifier("name"),
|
||||
createIdentifier("v")
|
||||
]
|
||||
)
|
||||
)
|
||||
])
|
||||
);
|
||||
|
||||
// return name => cache[name] || ...
|
||||
const getOrCreateAccessorsForName = createReturn(
|
||||
createArrowFunction(
|
||||
/*modifiers*/ undefined,
|
||||
/*typeParameters*/ undefined,
|
||||
[createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "name")],
|
||||
/*type*/ undefined,
|
||||
createToken(SyntaxKind.EqualsGreaterThanToken),
|
||||
createLogicalOr(
|
||||
createElementAccess(
|
||||
createIdentifier("cache"),
|
||||
createIdentifier("name")
|
||||
),
|
||||
createParen(
|
||||
createAssignment(
|
||||
createElementAccess(
|
||||
createIdentifier("cache"),
|
||||
createIdentifier("name")
|
||||
),
|
||||
createObjectLiteral([
|
||||
getter,
|
||||
setter
|
||||
])
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// const _super = (function (geti, seti) {
|
||||
// const cache = Object.create(null);
|
||||
// return name => cache[name] || (cache[name] = { get value() { return geti(name); }, set value(v) { seti(name, v); } });
|
||||
// })(name => super[name], (name, value) => super[name] = value);
|
||||
return createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
createConstDeclarationList([
|
||||
createVariableDeclaration(
|
||||
"_super",
|
||||
/*type*/ undefined,
|
||||
createCall(
|
||||
createParen(
|
||||
createFunctionExpression(
|
||||
/*modifiers*/ undefined,
|
||||
/*asteriskToken*/ undefined,
|
||||
/*name*/ undefined,
|
||||
/*typeParameters*/ undefined,
|
||||
[
|
||||
createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "geti"),
|
||||
createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "seti")
|
||||
],
|
||||
/*type*/ undefined,
|
||||
createBlock([
|
||||
createCache,
|
||||
getOrCreateAccessorsForName
|
||||
])
|
||||
)
|
||||
),
|
||||
/*typeArguments*/ undefined,
|
||||
[
|
||||
createGeti(createSuper()),
|
||||
createSeti(createSuper())
|
||||
]
|
||||
)
|
||||
)
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
export function createSimpleAsyncSuperHelper() {
|
||||
return createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
createConstDeclarationList([
|
||||
createVariableDeclaration(
|
||||
"_super",
|
||||
/*type*/ undefined,
|
||||
createGeti(createSuper())
|
||||
)
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
export interface CallBinding {
|
||||
@@ -2356,11 +2100,11 @@ namespace ts {
|
||||
/**
|
||||
* Ensures "use strict" directive is added
|
||||
*
|
||||
* @param node source file
|
||||
* @param statements An array of statements
|
||||
*/
|
||||
export function ensureUseStrict(node: SourceFile): SourceFile {
|
||||
export function ensureUseStrict(statements: NodeArray<Statement>): NodeArray<Statement> {
|
||||
let foundUseStrict = false;
|
||||
for (const statement of node.statements) {
|
||||
for (const statement of statements) {
|
||||
if (isPrologueDirective(statement)) {
|
||||
if (isUseStrictPrologue(statement as ExpressionStatement)) {
|
||||
foundUseStrict = true;
|
||||
@@ -2371,13 +2115,15 @@ namespace ts {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundUseStrict) {
|
||||
const statements: Statement[] = [];
|
||||
statements.push(startOnNewLine(createStatement(createLiteral("use strict"))));
|
||||
// add "use strict" as the first statement
|
||||
return updateSourceFileNode(node, statements.concat(node.statements));
|
||||
return createNodeArray<Statement>([
|
||||
startOnNewLine(createStatement(createLiteral("use strict"))),
|
||||
...statements
|
||||
], statements);
|
||||
}
|
||||
return node;
|
||||
|
||||
return statements;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2796,12 +2542,21 @@ namespace ts {
|
||||
}
|
||||
|
||||
function mergeEmitNode(sourceEmitNode: EmitNode, destEmitNode: EmitNode) {
|
||||
const { flags, commentRange, sourceMapRange, tokenSourceMapRanges } = sourceEmitNode;
|
||||
if (!destEmitNode && (flags || commentRange || sourceMapRange || tokenSourceMapRanges)) destEmitNode = {};
|
||||
const {
|
||||
flags,
|
||||
commentRange,
|
||||
sourceMapRange,
|
||||
tokenSourceMapRanges,
|
||||
constantValue,
|
||||
helpers
|
||||
} = sourceEmitNode;
|
||||
if (!destEmitNode) destEmitNode = {};
|
||||
if (flags) destEmitNode.flags = flags;
|
||||
if (commentRange) destEmitNode.commentRange = commentRange;
|
||||
if (sourceMapRange) destEmitNode.sourceMapRange = sourceMapRange;
|
||||
if (tokenSourceMapRanges) destEmitNode.tokenSourceMapRanges = mergeTokenSourceMapRanges(tokenSourceMapRanges, destEmitNode.tokenSourceMapRanges);
|
||||
if (constantValue !== undefined) destEmitNode.constantValue = constantValue;
|
||||
if (helpers) destEmitNode.helpers = addRange(destEmitNode.helpers, helpers);
|
||||
return destEmitNode;
|
||||
}
|
||||
|
||||
@@ -2879,6 +2634,16 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a custom text range to use when emitting source maps.
|
||||
*
|
||||
* @param node The node.
|
||||
*/
|
||||
export function getSourceMapRange(node: Node) {
|
||||
const emitNode = node.emitNode;
|
||||
return (emitNode && emitNode.sourceMapRange) || node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a custom text range to use when emitting source maps.
|
||||
*
|
||||
@@ -2890,6 +2655,18 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the TextRange to use for source maps for a token of a node.
|
||||
*
|
||||
* @param node The node.
|
||||
* @param token The token.
|
||||
*/
|
||||
export function getTokenSourceMapRange(node: Node, token: SyntaxKind) {
|
||||
const emitNode = node.emitNode;
|
||||
const tokenSourceMapRanges = emitNode && emitNode.tokenSourceMapRanges;
|
||||
return tokenSourceMapRanges && tokenSourceMapRanges[token];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the TextRange to use for source maps for a token of a node.
|
||||
*
|
||||
@@ -2904,14 +2681,6 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a custom text range to use when emitting comments.
|
||||
*/
|
||||
export function setCommentRange<T extends Node>(node: T, range: TextRange) {
|
||||
getOrCreateEmitNode(node).commentRange = range;
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a custom text range to use when emitting comments.
|
||||
*
|
||||
@@ -2923,25 +2692,11 @@ namespace ts {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a custom text range to use when emitting source maps.
|
||||
*
|
||||
* @param node The node.
|
||||
* Sets a custom text range to use when emitting comments.
|
||||
*/
|
||||
export function getSourceMapRange(node: Node) {
|
||||
const emitNode = node.emitNode;
|
||||
return (emitNode && emitNode.sourceMapRange) || node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the TextRange to use for source maps for a token of a node.
|
||||
*
|
||||
* @param node The node.
|
||||
* @param token The token.
|
||||
*/
|
||||
export function getTokenSourceMapRange(node: Node, token: SyntaxKind) {
|
||||
const emitNode = node.emitNode;
|
||||
const tokenSourceMapRanges = emitNode && emitNode.tokenSourceMapRanges;
|
||||
return tokenSourceMapRanges && tokenSourceMapRanges[token];
|
||||
export function setCommentRange<T extends Node>(node: T, range: TextRange) {
|
||||
getOrCreateEmitNode(node).commentRange = range;
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2961,6 +2716,102 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
export function getExternalHelpersModuleName(node: SourceFile) {
|
||||
const parseNode = getOriginalNode(node, isSourceFile);
|
||||
const emitNode = parseNode && parseNode.emitNode;
|
||||
return emitNode && emitNode.externalHelpersModuleName;
|
||||
}
|
||||
|
||||
export function getOrCreateExternalHelpersModuleName(node: SourceFile, compilerOptions: CompilerOptions) {
|
||||
if (compilerOptions.importHelpers && (isExternalModule(node) || compilerOptions.isolatedModules)) {
|
||||
const parseNode = getOriginalNode(node, isSourceFile);
|
||||
const emitNode = getOrCreateEmitNode(parseNode);
|
||||
return emitNode.externalHelpersModuleName || (emitNode.externalHelpersModuleName = createUniqueName(externalHelpersModuleNameText));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an EmitHelper to a node.
|
||||
*/
|
||||
export function addEmitHelper<T extends Node>(node: T, helper: EmitHelper): T {
|
||||
const emitNode = getOrCreateEmitNode(node);
|
||||
emitNode.helpers = append(emitNode.helpers, helper);
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an EmitHelper to a node.
|
||||
*/
|
||||
export function addEmitHelpers<T extends Node>(node: T, helpers: EmitHelper[] | undefined): T {
|
||||
if (some(helpers)) {
|
||||
const emitNode = getOrCreateEmitNode(node);
|
||||
for (const helper of helpers) {
|
||||
if (!contains(emitNode.helpers, helper)) {
|
||||
emitNode.helpers = append(emitNode.helpers, helper);
|
||||
}
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an EmitHelper from a node.
|
||||
*/
|
||||
export function removeEmitHelper(node: Node, helper: EmitHelper): boolean {
|
||||
const emitNode = node.emitNode;
|
||||
if (emitNode) {
|
||||
const helpers = emitNode.helpers;
|
||||
if (helpers) {
|
||||
return orderedRemoveItem(helpers, helper);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the EmitHelpers of a node.
|
||||
*/
|
||||
export function getEmitHelpers(node: Node): EmitHelper[] | undefined {
|
||||
const emitNode = node.emitNode;
|
||||
return emitNode && emitNode.helpers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves matching emit helpers from a source node to a target node.
|
||||
*/
|
||||
export function moveEmitHelpers(source: Node, target: Node, predicate: (helper: EmitHelper) => boolean) {
|
||||
const sourceEmitNode = source.emitNode;
|
||||
const sourceEmitHelpers = sourceEmitNode && sourceEmitNode.helpers;
|
||||
if (!some(sourceEmitHelpers)) return;
|
||||
|
||||
const targetEmitNode = getOrCreateEmitNode(target);
|
||||
let helpersRemoved = 0;
|
||||
for (let i = 0; i < sourceEmitHelpers.length; i++) {
|
||||
const helper = sourceEmitHelpers[i];
|
||||
if (predicate(helper)) {
|
||||
helpersRemoved++;
|
||||
if (!contains(targetEmitNode.helpers, helper)) {
|
||||
targetEmitNode.helpers = append(targetEmitNode.helpers, helper);
|
||||
}
|
||||
}
|
||||
else if (helpersRemoved > 0) {
|
||||
sourceEmitHelpers[i - helpersRemoved] = helper;
|
||||
}
|
||||
}
|
||||
|
||||
if (helpersRemoved > 0) {
|
||||
sourceEmitHelpers.length -= helpersRemoved;
|
||||
}
|
||||
}
|
||||
|
||||
export function compareEmitHelpers(x: EmitHelper, y: EmitHelper) {
|
||||
if (x === y) return Comparison.EqualTo;
|
||||
if (x.priority === y.priority) return Comparison.EqualTo;
|
||||
if (x.priority === undefined) return Comparison.GreaterThan;
|
||||
if (y.priority === undefined) return Comparison.LessThan;
|
||||
return compareValues(x.priority, y.priority);
|
||||
}
|
||||
|
||||
export function setTextRange<T extends TextRange>(node: T, location: TextRange): T {
|
||||
if (location) {
|
||||
node.pos = location.pos;
|
||||
@@ -3055,4 +2906,164 @@ namespace ts {
|
||||
function tryGetModuleNameFromDeclaration(declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration, host: EmitHost, resolver: EmitResolver, compilerOptions: CompilerOptions) {
|
||||
return tryGetModuleNameFromFile(resolver.getExternalModuleFileFromDeclaration(declaration), host, compilerOptions);
|
||||
}
|
||||
|
||||
export interface ExternalModuleInfo {
|
||||
externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[]; // imports of other external modules
|
||||
externalHelpersImportDeclaration: ImportDeclaration | undefined; // import of external helpers
|
||||
exportSpecifiers: Map<ExportSpecifier[]>; // export specifiers by name
|
||||
exportedBindings: Map<Identifier[]>; // exported names of local declarations
|
||||
exportedNames: Identifier[]; // all exported names local to module
|
||||
exportEquals: ExportAssignment | undefined; // an export= declaration if one was present
|
||||
hasExportStarsToExportValues: boolean; // whether this module contains export*
|
||||
}
|
||||
|
||||
export function collectExternalModuleInfo(sourceFile: SourceFile, resolver: EmitResolver): ExternalModuleInfo {
|
||||
const externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[] = [];
|
||||
const exportSpecifiers = createMap<ExportSpecifier[]>();
|
||||
const exportedBindings = createMap<Identifier[]>();
|
||||
const uniqueExports = createMap<Identifier>();
|
||||
let hasExportDefault = false;
|
||||
let exportEquals: ExportAssignment = undefined;
|
||||
let hasExportStarsToExportValues = false;
|
||||
|
||||
const externalHelpersModuleName = getExternalHelpersModuleName(sourceFile);
|
||||
const externalHelpersImportDeclaration = externalHelpersModuleName && createImportDeclaration(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
createImportClause(/*name*/ undefined, createNamespaceImport(externalHelpersModuleName)),
|
||||
createLiteral(externalHelpersModuleNameText));
|
||||
|
||||
if (externalHelpersImportDeclaration) {
|
||||
externalImports.push(externalHelpersImportDeclaration);
|
||||
}
|
||||
|
||||
for (const node of sourceFile.statements) {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ImportDeclaration:
|
||||
// import "mod"
|
||||
// import x from "mod"
|
||||
// import * as x from "mod"
|
||||
// import { x, y } from "mod"
|
||||
externalImports.push(<ImportDeclaration>node);
|
||||
break;
|
||||
|
||||
case SyntaxKind.ImportEqualsDeclaration:
|
||||
if ((<ImportEqualsDeclaration>node).moduleReference.kind === SyntaxKind.ExternalModuleReference) {
|
||||
// import x = require("mod")
|
||||
externalImports.push(<ImportEqualsDeclaration>node);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SyntaxKind.ExportDeclaration:
|
||||
if ((<ExportDeclaration>node).moduleSpecifier) {
|
||||
if (!(<ExportDeclaration>node).exportClause) {
|
||||
// export * from "mod"
|
||||
externalImports.push(<ExportDeclaration>node);
|
||||
hasExportStarsToExportValues = true;
|
||||
}
|
||||
else {
|
||||
// export { x, y } from "mod"
|
||||
externalImports.push(<ExportDeclaration>node);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// export { x, y }
|
||||
for (const specifier of (<ExportDeclaration>node).exportClause.elements) {
|
||||
if (!uniqueExports[specifier.name.text]) {
|
||||
const name = specifier.propertyName || specifier.name;
|
||||
multiMapAdd(exportSpecifiers, name.text, specifier);
|
||||
|
||||
const decl = resolver.getReferencedImportDeclaration(name)
|
||||
|| resolver.getReferencedValueDeclaration(name);
|
||||
|
||||
if (decl) {
|
||||
multiMapAdd(exportedBindings, getOriginalNodeId(decl), specifier.name);
|
||||
}
|
||||
|
||||
uniqueExports[specifier.name.text] = specifier.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SyntaxKind.ExportAssignment:
|
||||
if ((<ExportAssignment>node).isExportEquals && !exportEquals) {
|
||||
// export = x
|
||||
exportEquals = <ExportAssignment>node;
|
||||
}
|
||||
break;
|
||||
|
||||
case SyntaxKind.VariableStatement:
|
||||
if (hasModifier(node, ModifierFlags.Export)) {
|
||||
for (const decl of (<VariableStatement>node).declarationList.declarations) {
|
||||
collectExportedVariableInfo(decl, uniqueExports);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
if (hasModifier(node, ModifierFlags.Export)) {
|
||||
if (hasModifier(node, ModifierFlags.Default)) {
|
||||
// export default function() { }
|
||||
if (!hasExportDefault) {
|
||||
multiMapAdd(exportedBindings, getOriginalNodeId(node), getDeclarationName(<FunctionDeclaration>node));
|
||||
hasExportDefault = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// export function x() { }
|
||||
const name = (<FunctionDeclaration>node).name;
|
||||
if (!uniqueExports[name.text]) {
|
||||
multiMapAdd(exportedBindings, getOriginalNodeId(node), name);
|
||||
uniqueExports[name.text] = name;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
if (hasModifier(node, ModifierFlags.Export)) {
|
||||
if (hasModifier(node, ModifierFlags.Default)) {
|
||||
// export default class { }
|
||||
if (!hasExportDefault) {
|
||||
multiMapAdd(exportedBindings, getOriginalNodeId(node), getDeclarationName(<ClassDeclaration>node));
|
||||
hasExportDefault = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// export class x { }
|
||||
const name = (<ClassDeclaration>node).name;
|
||||
if (!uniqueExports[name.text]) {
|
||||
multiMapAdd(exportedBindings, getOriginalNodeId(node), name);
|
||||
uniqueExports[name.text] = name;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let exportedNames: Identifier[];
|
||||
for (const key in uniqueExports) {
|
||||
exportedNames = ts.append(exportedNames, uniqueExports[key]);
|
||||
}
|
||||
|
||||
return { externalImports, exportSpecifiers, exportEquals, hasExportStarsToExportValues, exportedBindings, exportedNames, externalHelpersImportDeclaration };
|
||||
}
|
||||
|
||||
function collectExportedVariableInfo(decl: VariableDeclaration | BindingElement, uniqueExports: Map<Identifier>) {
|
||||
if (isBindingPattern(decl.name)) {
|
||||
for (const element of decl.name.elements) {
|
||||
if (!isOmittedExpression(element)) {
|
||||
collectExportedVariableInfo(element, uniqueExports);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!isGeneratedIdentifier(decl.name)) {
|
||||
if (!uniqueExports[decl.name.text]) {
|
||||
uniqueExports[decl.name.text] = decl.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
/*@internal*/
|
||||
namespace ts {
|
||||
|
||||
const enum ES2015SubstitutionFlags {
|
||||
/** Enables substitutions for captured `this` */
|
||||
CapturedThis = 1 << 0,
|
||||
@@ -170,6 +169,7 @@ namespace ts {
|
||||
hoistVariableDeclaration,
|
||||
} = context;
|
||||
|
||||
const compilerOptions = context.getCompilerOptions();
|
||||
const resolver = context.getEmitResolver();
|
||||
const previousOnSubstituteNode = context.onSubstituteNode;
|
||||
const previousOnEmitNode = context.onEmitNode;
|
||||
@@ -187,6 +187,7 @@ namespace ts {
|
||||
let enclosingNonArrowFunction: FunctionLikeDeclaration;
|
||||
let enclosingNonAsyncFunctionBody: FunctionLikeDeclaration | ClassElement;
|
||||
let isInConstructorWithCapturedSuper: boolean;
|
||||
let helperState: EmitHelperState;
|
||||
|
||||
/**
|
||||
* Used to track if we are emitting body of the converted loop
|
||||
@@ -209,7 +210,15 @@ namespace ts {
|
||||
|
||||
currentSourceFile = node;
|
||||
currentText = node.text;
|
||||
return visitNode(node, visitor, isSourceFile);
|
||||
helperState = { currentSourceFile, compilerOptions };
|
||||
|
||||
const visited = visitNode(node, visitor, isSourceFile);
|
||||
addEmitHelpers(visited, helperState.requestedHelpers);
|
||||
|
||||
currentSourceFile = undefined;
|
||||
currentText = undefined;
|
||||
helperState = undefined;
|
||||
return visited;
|
||||
}
|
||||
|
||||
function visitor(node: Node): VisitResult<Node> {
|
||||
@@ -778,7 +787,7 @@ namespace ts {
|
||||
if (extendsClauseElement) {
|
||||
statements.push(
|
||||
createStatement(
|
||||
createExtendsHelper(currentSourceFile.externalHelpersModuleName, getLocalName(node)),
|
||||
createExtendsHelper(helperState, getLocalName(node)),
|
||||
/*location*/ extendsClauseElement
|
||||
)
|
||||
);
|
||||
@@ -3274,4 +3283,28 @@ namespace ts {
|
||||
return isIdentifier(expression) && expression === parameter.name;
|
||||
}
|
||||
}
|
||||
|
||||
function createExtendsHelper(helperState: EmitHelperState, name: Identifier) {
|
||||
requestEmitHelper(helperState, extendsHelper);
|
||||
return createCall(
|
||||
getHelperName(helperState, "__extends"),
|
||||
/*typeArguments*/ undefined,
|
||||
[
|
||||
name,
|
||||
createIdentifier("_super")
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
const extendsHelper: EmitHelper = {
|
||||
name: "typescript:extends",
|
||||
scoped: false,
|
||||
priority: 0,
|
||||
text: `
|
||||
var __extends = (this && this.__extends) || function (d, b) {
|
||||
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};`
|
||||
};
|
||||
}
|
||||
|
||||
@@ -5,13 +5,12 @@
|
||||
namespace ts {
|
||||
type SuperContainer = ClassDeclaration | MethodDeclaration | GetAccessorDeclaration | SetAccessorDeclaration | ConstructorDeclaration;
|
||||
|
||||
const enum ES2017SubstitutionFlags {
|
||||
/** Enables substitutions for async methods with `super` calls. */
|
||||
AsyncMethodsWithSuper = 1 << 0
|
||||
}
|
||||
|
||||
export function transformES2017(context: TransformationContext) {
|
||||
|
||||
const enum ES2017SubstitutionFlags {
|
||||
/** Enables substitutions for async methods with `super` calls. */
|
||||
AsyncMethodsWithSuper = 1 << 0
|
||||
}
|
||||
|
||||
const {
|
||||
startLexicalEnvironment,
|
||||
endLexicalEnvironment,
|
||||
@@ -22,7 +21,9 @@ namespace ts {
|
||||
const languageVersion = getEmitScriptTarget(compilerOptions);
|
||||
|
||||
// These variables contain state that changes as we descend into the tree.
|
||||
let currentSourceFileExternalHelpersModuleName: Identifier;
|
||||
let currentSourceFile: SourceFile;
|
||||
let helperState: EmitHelperState;
|
||||
|
||||
/**
|
||||
* Keeps track of whether expression substitution has been enabled for specific edge cases.
|
||||
* They are persisted between each SourceFile transformation and should not be reset.
|
||||
@@ -58,9 +59,16 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
currentSourceFileExternalHelpersModuleName = node.externalHelpersModuleName;
|
||||
currentSourceFile = node;
|
||||
helperState = { currentSourceFile, compilerOptions };
|
||||
|
||||
return visitEachChild(node, visitor, context);
|
||||
const visited = visitEachChild(node, visitor, context);
|
||||
|
||||
addEmitHelpers(visited, helperState.requestedHelpers);
|
||||
|
||||
currentSourceFile = undefined;
|
||||
helperState = undefined;
|
||||
return visited;
|
||||
}
|
||||
|
||||
function visitor(node: Node): VisitResult<Node> {
|
||||
@@ -107,11 +115,11 @@ namespace ts {
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits an await expression.
|
||||
* Visits an AwaitExpression node.
|
||||
*
|
||||
* This function will be called any time a ES2017 await expression is encountered.
|
||||
*
|
||||
* @param node The await expression node.
|
||||
* @param node The node to visit.
|
||||
*/
|
||||
function visitAwaitExpression(node: AwaitExpression): Expression {
|
||||
return setOriginalNode(
|
||||
@@ -125,17 +133,15 @@ namespace ts {
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a method declaration of a class.
|
||||
* Visits a MethodDeclaration node.
|
||||
*
|
||||
* This function will be called when one of the following conditions are met:
|
||||
* - The node is marked as async
|
||||
*
|
||||
* @param node The method node.
|
||||
* @param node The node to visit.
|
||||
*/
|
||||
function visitMethodDeclaration(node: MethodDeclaration) {
|
||||
if (!isAsyncFunctionLike(node)) {
|
||||
return node;
|
||||
}
|
||||
Debug.assert(hasModifier(node, ModifierFlags.Async));
|
||||
const method = createMethod(
|
||||
/*decorators*/ undefined,
|
||||
visitNodes(node.modifiers, visitor, isModifier),
|
||||
@@ -150,25 +156,20 @@ namespace ts {
|
||||
|
||||
// While we emit the source map for the node after skipping decorators and modifiers,
|
||||
// we need to emit the comments for the original range.
|
||||
setCommentRange(method, node);
|
||||
setSourceMapRange(method, moveRangePastDecorators(node));
|
||||
setOriginalNode(method, node);
|
||||
|
||||
return method;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a function declaration.
|
||||
* Visits a FunctionDeclaration node.
|
||||
*
|
||||
* This function will be called when one of the following conditions are met:
|
||||
* - The node is marked async
|
||||
*
|
||||
* @param node The function node.
|
||||
* @param node The node to visit.
|
||||
*/
|
||||
function visitFunctionDeclaration(node: FunctionDeclaration): VisitResult<Statement> {
|
||||
if (!isAsyncFunctionLike(node)) {
|
||||
return node;
|
||||
}
|
||||
Debug.assert(hasModifier(node, ModifierFlags.Async));
|
||||
const func = createFunctionDeclaration(
|
||||
/*decorators*/ undefined,
|
||||
visitNodes(node.modifiers, visitor, isModifier),
|
||||
@@ -180,23 +181,21 @@ namespace ts {
|
||||
transformFunctionBody(node),
|
||||
/*location*/ node
|
||||
);
|
||||
setOriginalNode(func, node);
|
||||
|
||||
setOriginalNode(func, node);
|
||||
return func;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a function expression node.
|
||||
* Visits a FunctionExpression node.
|
||||
*
|
||||
* This function will be called when one of the following conditions are met:
|
||||
* - The node is marked async
|
||||
*
|
||||
* @param node The function expression node.
|
||||
* @param node The node to visit.
|
||||
*/
|
||||
function visitFunctionExpression(node: FunctionExpression): Expression {
|
||||
if (!isAsyncFunctionLike(node)) {
|
||||
return node;
|
||||
}
|
||||
Debug.assert(hasModifier(node, ModifierFlags.Async));
|
||||
if (nodeIsMissing(node.body)) {
|
||||
return createOmittedExpression();
|
||||
}
|
||||
@@ -213,19 +212,19 @@ namespace ts {
|
||||
);
|
||||
|
||||
setOriginalNode(func, node);
|
||||
|
||||
return func;
|
||||
}
|
||||
|
||||
/**
|
||||
* @remarks
|
||||
* Visits an ArrowFunction.
|
||||
*
|
||||
* This function will be called when one of the following conditions are met:
|
||||
* - The node is marked async
|
||||
*
|
||||
* @param node The node to visit.
|
||||
*/
|
||||
function visitArrowFunction(node: ArrowFunction) {
|
||||
if (!isAsyncFunctionLike(node)) {
|
||||
return node;
|
||||
}
|
||||
Debug.assert(hasModifier(node, ModifierFlags.Async));
|
||||
const func = createArrowFunction(
|
||||
visitNodes(node.modifiers, visitor, isModifier),
|
||||
/*typeParameters*/ undefined,
|
||||
@@ -237,7 +236,6 @@ namespace ts {
|
||||
);
|
||||
|
||||
setOriginalNode(func, node);
|
||||
|
||||
return func;
|
||||
}
|
||||
|
||||
@@ -280,7 +278,7 @@ namespace ts {
|
||||
statements.push(
|
||||
createReturn(
|
||||
createAwaiterHelper(
|
||||
currentSourceFileExternalHelpersModuleName,
|
||||
helperState,
|
||||
hasLexicalArguments,
|
||||
promiseConstructor,
|
||||
transformFunctionBodyWorker(<Block>node.body, statementOffset)
|
||||
@@ -295,11 +293,11 @@ namespace ts {
|
||||
if (languageVersion >= ScriptTarget.ES2015) {
|
||||
if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.AsyncMethodWithSuperBinding) {
|
||||
enableSubstitutionForAsyncMethodsWithSuper();
|
||||
setEmitFlags(block, EmitFlags.EmitAdvancedSuperHelper);
|
||||
addEmitHelper(block, advancedAsyncSuperHelper);
|
||||
}
|
||||
else if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.AsyncMethodWithSuper) {
|
||||
enableSubstitutionForAsyncMethodsWithSuper();
|
||||
setEmitFlags(block, EmitFlags.EmitSuperHelper);
|
||||
addEmitHelper(block, asyncSuperHelper);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -307,7 +305,7 @@ namespace ts {
|
||||
}
|
||||
else {
|
||||
return createAwaiterHelper(
|
||||
currentSourceFileExternalHelpersModuleName,
|
||||
helperState,
|
||||
hasLexicalArguments,
|
||||
promiseConstructor,
|
||||
<Block>transformConciseBodyWorker(node.body, /*forceBlockFunctionBody*/ true)
|
||||
@@ -507,4 +505,63 @@ namespace ts {
|
||||
&& resolver.getNodeCheckFlags(currentSuperContainer) & (NodeCheckFlags.AsyncMethodWithSuper | NodeCheckFlags.AsyncMethodWithSuperBinding);
|
||||
}
|
||||
}
|
||||
|
||||
function createAwaiterHelper(helperState: EmitHelperState, hasLexicalArguments: boolean, promiseConstructor: EntityName | Expression, body: Block) {
|
||||
const generatorFunc = createFunctionExpression(
|
||||
/*modifiers*/ undefined,
|
||||
createToken(SyntaxKind.AsteriskToken),
|
||||
/*name*/ undefined,
|
||||
/*typeParameters*/ undefined,
|
||||
/*parameters*/ [],
|
||||
/*type*/ undefined,
|
||||
body
|
||||
);
|
||||
|
||||
// Mark this node as originally an async function
|
||||
(generatorFunc.emitNode || (generatorFunc.emitNode = {})).flags |= EmitFlags.AsyncFunctionBody;
|
||||
|
||||
requestEmitHelper(helperState, awaiterHelper);
|
||||
return createCall(
|
||||
getHelperName(helperState, "__awaiter"),
|
||||
/*typeArguments*/ undefined,
|
||||
[
|
||||
createThis(),
|
||||
hasLexicalArguments ? createIdentifier("arguments") : createVoidZero(),
|
||||
promiseConstructor ? createExpressionFromEntityName(promiseConstructor) : createVoidZero(),
|
||||
generatorFunc
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
const awaiterHelper: EmitHelper = {
|
||||
name: "typescript:awaiter",
|
||||
scoped: false,
|
||||
priority: 5,
|
||||
text: `
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments)).next());
|
||||
});
|
||||
};`
|
||||
};
|
||||
|
||||
const asyncSuperHelper: EmitHelper = {
|
||||
name: "typescript:async-super",
|
||||
scoped: true,
|
||||
text: `
|
||||
const _super = name => super[name];`
|
||||
};
|
||||
|
||||
const advancedAsyncSuperHelper: EmitHelper = {
|
||||
name: "typescript:advanced-async-super",
|
||||
scoped: true,
|
||||
text: `
|
||||
const _super = (function (geti, seti) {
|
||||
const cache = Object.create(null);
|
||||
return name => cache[name] || (cache[name] = { get value() { return geti(name); }, set value(v) { seti(name, v); } });
|
||||
})(name => super[name], (name, value) => super[name] = value);`
|
||||
};
|
||||
}
|
||||
|
||||
@@ -242,6 +242,7 @@ namespace ts {
|
||||
let currentSourceFile: SourceFile;
|
||||
let renamedCatchVariables: Map<boolean>;
|
||||
let renamedCatchVariableDeclarations: Map<Identifier>;
|
||||
let helperState: EmitHelperState;
|
||||
|
||||
let inGeneratorFunctionBody: boolean;
|
||||
let inStatementContainingYield: boolean;
|
||||
@@ -291,17 +292,20 @@ namespace ts {
|
||||
return transformSourceFile;
|
||||
|
||||
function transformSourceFile(node: SourceFile) {
|
||||
if (isDeclarationFile(node)) {
|
||||
if (isDeclarationFile(node)
|
||||
|| (node.transformFlags & TransformFlags.ContainsGenerator) === 0) {
|
||||
return node;
|
||||
}
|
||||
|
||||
if (node.transformFlags & TransformFlags.ContainsGenerator) {
|
||||
currentSourceFile = node;
|
||||
node = visitEachChild(node, visitor, context);
|
||||
currentSourceFile = undefined;
|
||||
}
|
||||
currentSourceFile = node;
|
||||
helperState = { currentSourceFile, compilerOptions };
|
||||
|
||||
return node;
|
||||
const visited = visitEachChild(node, visitor, context);
|
||||
addEmitHelpers(visited, helperState.requestedHelpers);
|
||||
|
||||
currentSourceFile = undefined;
|
||||
helperState = undefined;
|
||||
return visited;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2585,28 +2589,24 @@ namespace ts {
|
||||
withBlockStack = undefined;
|
||||
|
||||
const buildResult = buildStatements();
|
||||
return createCall(
|
||||
createHelperName(currentSourceFile.externalHelpersModuleName, "__generator"),
|
||||
/*typeArguments*/ undefined,
|
||||
[
|
||||
createThis(),
|
||||
setEmitFlags(
|
||||
createFunctionExpression(
|
||||
/*modifiers*/ undefined,
|
||||
/*asteriskToken*/ undefined,
|
||||
/*name*/ undefined,
|
||||
/*typeParameters*/ undefined,
|
||||
[createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, state)],
|
||||
/*type*/ undefined,
|
||||
createBlock(
|
||||
buildResult,
|
||||
/*location*/ undefined,
|
||||
/*multiLine*/ buildResult.length > 0
|
||||
)
|
||||
),
|
||||
EmitFlags.ReuseTempVariableScope
|
||||
)
|
||||
]
|
||||
return createGeneratorHelper(
|
||||
helperState,
|
||||
setEmitFlags(
|
||||
createFunctionExpression(
|
||||
/*modifiers*/ undefined,
|
||||
/*asteriskToken*/ undefined,
|
||||
/*name*/ undefined,
|
||||
/*typeParameters*/ undefined,
|
||||
[createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, state)],
|
||||
/*type*/ undefined,
|
||||
createBlock(
|
||||
buildResult,
|
||||
/*location*/ undefined,
|
||||
/*multiLine*/ buildResult.length > 0
|
||||
)
|
||||
),
|
||||
EmitFlags.ReuseTempVariableScope
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3082,4 +3082,105 @@ namespace ts {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function createGeneratorHelper(helperState: EmitHelperState, body: FunctionExpression) {
|
||||
requestEmitHelper(helperState, generatorHelper);
|
||||
return createCall(
|
||||
getHelperName(helperState, "__generator"),
|
||||
/*typeArguments*/ undefined,
|
||||
[createThis(), body]);
|
||||
}
|
||||
|
||||
// The __generator helper is used by down-level transformations to emulate the runtime
|
||||
// semantics of an ES2015 generator function. When called, this helper returns an
|
||||
// object that implements the Iterator protocol, in that it has `next`, `return`, and
|
||||
// `throw` methods that step through the generator when invoked.
|
||||
//
|
||||
// parameters:
|
||||
// thisArg The value to use as the `this` binding for the transformed generator body.
|
||||
// body A function that acts as the transformed generator body.
|
||||
//
|
||||
// variables:
|
||||
// _ Persistent state for the generator that is shared between the helper and the
|
||||
// generator body. The state object has the following members:
|
||||
// sent() - A method that returns or throws the current completion value.
|
||||
// label - The next point at which to resume evaluation of the generator body.
|
||||
// trys - A stack of protected regions (try/catch/finally blocks).
|
||||
// ops - A stack of pending instructions when inside of a finally block.
|
||||
// f A value indicating whether the generator is executing.
|
||||
// y An iterator to delegate for a yield*.
|
||||
// t A temporary variable that holds one of the following values (note that these
|
||||
// cases do not overlap):
|
||||
// - The completion value when resuming from a `yield` or `yield*`.
|
||||
// - The error value for a catch block.
|
||||
// - The current protected region (array of try/catch/finally/end labels).
|
||||
// - The verb (`next`, `throw`, or `return` method) to delegate to the expression
|
||||
// of a `yield*`.
|
||||
// - The result of evaluating the verb delegated to the expression of a `yield*`.
|
||||
//
|
||||
// functions:
|
||||
// verb(n) Creates a bound callback to the `step` function for opcode `n`.
|
||||
// step(op) Evaluates opcodes in a generator body until execution is suspended or
|
||||
// completed.
|
||||
//
|
||||
// The __generator helper understands a limited set of instructions:
|
||||
// 0: next(value?) - Start or resume the generator with the specified value.
|
||||
// 1: throw(error) - Resume the generator with an exception. If the generator is
|
||||
// suspended inside of one or more protected regions, evaluates
|
||||
// any intervening finally blocks between the current label and
|
||||
// the nearest catch block or function boundary. If uncaught, the
|
||||
// exception is thrown to the caller.
|
||||
// 2: return(value?) - Resume the generator as if with a return. If the generator is
|
||||
// suspended inside of one or more protected regions, evaluates any
|
||||
// intervening finally blocks.
|
||||
// 3: break(label) - Jump to the specified label. If the label is outside of the
|
||||
// current protected region, evaluates any intervening finally
|
||||
// blocks.
|
||||
// 4: yield(value?) - Yield execution to the caller with an optional value. When
|
||||
// resumed, the generator will continue at the next label.
|
||||
// 5: yield*(value) - Delegates evaluation to the supplied iterator. When
|
||||
// delegation completes, the generator will continue at the next
|
||||
// label.
|
||||
// 6: catch(error) - Handles an exception thrown from within the generator body. If
|
||||
// the current label is inside of one or more protected regions,
|
||||
// evaluates any intervening finally blocks between the current
|
||||
// label and the nearest catch block or function boundary. If
|
||||
// uncaught, the exception is thrown to the caller.
|
||||
// 7: endfinally - Ends a finally block, resuming the last instruction prior to
|
||||
// entering a finally block.
|
||||
//
|
||||
// For examples of how these are used, see the comments in ./transformers/generators.ts
|
||||
const generatorHelper: EmitHelper = {
|
||||
name: "typescript:generator",
|
||||
scoped: false,
|
||||
priority: 6,
|
||||
text: `
|
||||
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t;
|
||||
return { next: verb(0), "throw": verb(1), "return": verb(2) };
|
||||
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||
function step(op) {
|
||||
if (f) throw new TypeError("Generator is already executing.");
|
||||
while (_) try {
|
||||
if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t;
|
||||
if (y = 0, t) op = [0, t.value];
|
||||
switch (op[0]) {
|
||||
case 0: case 1: t = op; break;
|
||||
case 4: _.label++; return { value: op[1], done: false };
|
||||
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||
default:
|
||||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||
if (t[2]) _.ops.pop();
|
||||
_.trys.pop(); continue;
|
||||
}
|
||||
op = body.call(thisArg, _);
|
||||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||
}
|
||||
};`
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
|
||||
/*@internal*/
|
||||
namespace ts {
|
||||
const entities: Map<number> = createEntitiesMap();
|
||||
|
||||
export function transformJsx(context: TransformationContext) {
|
||||
const compilerOptions = context.getCompilerOptions();
|
||||
let currentSourceFile: SourceFile;
|
||||
let helperState: EmitHelperState;
|
||||
|
||||
return transformSourceFile;
|
||||
|
||||
/**
|
||||
@@ -21,9 +21,14 @@ namespace ts {
|
||||
}
|
||||
|
||||
currentSourceFile = node;
|
||||
node = visitEachChild(node, visitor, context);
|
||||
helperState = { currentSourceFile, compilerOptions };
|
||||
|
||||
const visited = visitEachChild(node, visitor, context);
|
||||
addEmitHelpers(visited, helperState.requestedHelpers);
|
||||
|
||||
currentSourceFile = undefined;
|
||||
return node;
|
||||
helperState = undefined;
|
||||
return visited;
|
||||
}
|
||||
|
||||
function visitor(node: Node): VisitResult<Node> {
|
||||
@@ -109,8 +114,10 @@ namespace ts {
|
||||
|
||||
// Either emit one big object literal (no spread attribs), or
|
||||
// a call to the __assign helper.
|
||||
objectProperties = singleOrUndefined(segments)
|
||||
|| createAssignHelper(currentSourceFile.externalHelpersModuleName, segments);
|
||||
objectProperties = singleOrUndefined(segments);
|
||||
if (!objectProperties) {
|
||||
objectProperties = createAssignHelper(helperState, segments);
|
||||
}
|
||||
}
|
||||
|
||||
const element = createReactCreateElement(
|
||||
@@ -275,261 +282,283 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function createEntitiesMap(): Map<number> {
|
||||
return createMap<number>({
|
||||
"quot": 0x0022,
|
||||
"amp": 0x0026,
|
||||
"apos": 0x0027,
|
||||
"lt": 0x003C,
|
||||
"gt": 0x003E,
|
||||
"nbsp": 0x00A0,
|
||||
"iexcl": 0x00A1,
|
||||
"cent": 0x00A2,
|
||||
"pound": 0x00A3,
|
||||
"curren": 0x00A4,
|
||||
"yen": 0x00A5,
|
||||
"brvbar": 0x00A6,
|
||||
"sect": 0x00A7,
|
||||
"uml": 0x00A8,
|
||||
"copy": 0x00A9,
|
||||
"ordf": 0x00AA,
|
||||
"laquo": 0x00AB,
|
||||
"not": 0x00AC,
|
||||
"shy": 0x00AD,
|
||||
"reg": 0x00AE,
|
||||
"macr": 0x00AF,
|
||||
"deg": 0x00B0,
|
||||
"plusmn": 0x00B1,
|
||||
"sup2": 0x00B2,
|
||||
"sup3": 0x00B3,
|
||||
"acute": 0x00B4,
|
||||
"micro": 0x00B5,
|
||||
"para": 0x00B6,
|
||||
"middot": 0x00B7,
|
||||
"cedil": 0x00B8,
|
||||
"sup1": 0x00B9,
|
||||
"ordm": 0x00BA,
|
||||
"raquo": 0x00BB,
|
||||
"frac14": 0x00BC,
|
||||
"frac12": 0x00BD,
|
||||
"frac34": 0x00BE,
|
||||
"iquest": 0x00BF,
|
||||
"Agrave": 0x00C0,
|
||||
"Aacute": 0x00C1,
|
||||
"Acirc": 0x00C2,
|
||||
"Atilde": 0x00C3,
|
||||
"Auml": 0x00C4,
|
||||
"Aring": 0x00C5,
|
||||
"AElig": 0x00C6,
|
||||
"Ccedil": 0x00C7,
|
||||
"Egrave": 0x00C8,
|
||||
"Eacute": 0x00C9,
|
||||
"Ecirc": 0x00CA,
|
||||
"Euml": 0x00CB,
|
||||
"Igrave": 0x00CC,
|
||||
"Iacute": 0x00CD,
|
||||
"Icirc": 0x00CE,
|
||||
"Iuml": 0x00CF,
|
||||
"ETH": 0x00D0,
|
||||
"Ntilde": 0x00D1,
|
||||
"Ograve": 0x00D2,
|
||||
"Oacute": 0x00D3,
|
||||
"Ocirc": 0x00D4,
|
||||
"Otilde": 0x00D5,
|
||||
"Ouml": 0x00D6,
|
||||
"times": 0x00D7,
|
||||
"Oslash": 0x00D8,
|
||||
"Ugrave": 0x00D9,
|
||||
"Uacute": 0x00DA,
|
||||
"Ucirc": 0x00DB,
|
||||
"Uuml": 0x00DC,
|
||||
"Yacute": 0x00DD,
|
||||
"THORN": 0x00DE,
|
||||
"szlig": 0x00DF,
|
||||
"agrave": 0x00E0,
|
||||
"aacute": 0x00E1,
|
||||
"acirc": 0x00E2,
|
||||
"atilde": 0x00E3,
|
||||
"auml": 0x00E4,
|
||||
"aring": 0x00E5,
|
||||
"aelig": 0x00E6,
|
||||
"ccedil": 0x00E7,
|
||||
"egrave": 0x00E8,
|
||||
"eacute": 0x00E9,
|
||||
"ecirc": 0x00EA,
|
||||
"euml": 0x00EB,
|
||||
"igrave": 0x00EC,
|
||||
"iacute": 0x00ED,
|
||||
"icirc": 0x00EE,
|
||||
"iuml": 0x00EF,
|
||||
"eth": 0x00F0,
|
||||
"ntilde": 0x00F1,
|
||||
"ograve": 0x00F2,
|
||||
"oacute": 0x00F3,
|
||||
"ocirc": 0x00F4,
|
||||
"otilde": 0x00F5,
|
||||
"ouml": 0x00F6,
|
||||
"divide": 0x00F7,
|
||||
"oslash": 0x00F8,
|
||||
"ugrave": 0x00F9,
|
||||
"uacute": 0x00FA,
|
||||
"ucirc": 0x00FB,
|
||||
"uuml": 0x00FC,
|
||||
"yacute": 0x00FD,
|
||||
"thorn": 0x00FE,
|
||||
"yuml": 0x00FF,
|
||||
"OElig": 0x0152,
|
||||
"oelig": 0x0153,
|
||||
"Scaron": 0x0160,
|
||||
"scaron": 0x0161,
|
||||
"Yuml": 0x0178,
|
||||
"fnof": 0x0192,
|
||||
"circ": 0x02C6,
|
||||
"tilde": 0x02DC,
|
||||
"Alpha": 0x0391,
|
||||
"Beta": 0x0392,
|
||||
"Gamma": 0x0393,
|
||||
"Delta": 0x0394,
|
||||
"Epsilon": 0x0395,
|
||||
"Zeta": 0x0396,
|
||||
"Eta": 0x0397,
|
||||
"Theta": 0x0398,
|
||||
"Iota": 0x0399,
|
||||
"Kappa": 0x039A,
|
||||
"Lambda": 0x039B,
|
||||
"Mu": 0x039C,
|
||||
"Nu": 0x039D,
|
||||
"Xi": 0x039E,
|
||||
"Omicron": 0x039F,
|
||||
"Pi": 0x03A0,
|
||||
"Rho": 0x03A1,
|
||||
"Sigma": 0x03A3,
|
||||
"Tau": 0x03A4,
|
||||
"Upsilon": 0x03A5,
|
||||
"Phi": 0x03A6,
|
||||
"Chi": 0x03A7,
|
||||
"Psi": 0x03A8,
|
||||
"Omega": 0x03A9,
|
||||
"alpha": 0x03B1,
|
||||
"beta": 0x03B2,
|
||||
"gamma": 0x03B3,
|
||||
"delta": 0x03B4,
|
||||
"epsilon": 0x03B5,
|
||||
"zeta": 0x03B6,
|
||||
"eta": 0x03B7,
|
||||
"theta": 0x03B8,
|
||||
"iota": 0x03B9,
|
||||
"kappa": 0x03BA,
|
||||
"lambda": 0x03BB,
|
||||
"mu": 0x03BC,
|
||||
"nu": 0x03BD,
|
||||
"xi": 0x03BE,
|
||||
"omicron": 0x03BF,
|
||||
"pi": 0x03C0,
|
||||
"rho": 0x03C1,
|
||||
"sigmaf": 0x03C2,
|
||||
"sigma": 0x03C3,
|
||||
"tau": 0x03C4,
|
||||
"upsilon": 0x03C5,
|
||||
"phi": 0x03C6,
|
||||
"chi": 0x03C7,
|
||||
"psi": 0x03C8,
|
||||
"omega": 0x03C9,
|
||||
"thetasym": 0x03D1,
|
||||
"upsih": 0x03D2,
|
||||
"piv": 0x03D6,
|
||||
"ensp": 0x2002,
|
||||
"emsp": 0x2003,
|
||||
"thinsp": 0x2009,
|
||||
"zwnj": 0x200C,
|
||||
"zwj": 0x200D,
|
||||
"lrm": 0x200E,
|
||||
"rlm": 0x200F,
|
||||
"ndash": 0x2013,
|
||||
"mdash": 0x2014,
|
||||
"lsquo": 0x2018,
|
||||
"rsquo": 0x2019,
|
||||
"sbquo": 0x201A,
|
||||
"ldquo": 0x201C,
|
||||
"rdquo": 0x201D,
|
||||
"bdquo": 0x201E,
|
||||
"dagger": 0x2020,
|
||||
"Dagger": 0x2021,
|
||||
"bull": 0x2022,
|
||||
"hellip": 0x2026,
|
||||
"permil": 0x2030,
|
||||
"prime": 0x2032,
|
||||
"Prime": 0x2033,
|
||||
"lsaquo": 0x2039,
|
||||
"rsaquo": 0x203A,
|
||||
"oline": 0x203E,
|
||||
"frasl": 0x2044,
|
||||
"euro": 0x20AC,
|
||||
"image": 0x2111,
|
||||
"weierp": 0x2118,
|
||||
"real": 0x211C,
|
||||
"trade": 0x2122,
|
||||
"alefsym": 0x2135,
|
||||
"larr": 0x2190,
|
||||
"uarr": 0x2191,
|
||||
"rarr": 0x2192,
|
||||
"darr": 0x2193,
|
||||
"harr": 0x2194,
|
||||
"crarr": 0x21B5,
|
||||
"lArr": 0x21D0,
|
||||
"uArr": 0x21D1,
|
||||
"rArr": 0x21D2,
|
||||
"dArr": 0x21D3,
|
||||
"hArr": 0x21D4,
|
||||
"forall": 0x2200,
|
||||
"part": 0x2202,
|
||||
"exist": 0x2203,
|
||||
"empty": 0x2205,
|
||||
"nabla": 0x2207,
|
||||
"isin": 0x2208,
|
||||
"notin": 0x2209,
|
||||
"ni": 0x220B,
|
||||
"prod": 0x220F,
|
||||
"sum": 0x2211,
|
||||
"minus": 0x2212,
|
||||
"lowast": 0x2217,
|
||||
"radic": 0x221A,
|
||||
"prop": 0x221D,
|
||||
"infin": 0x221E,
|
||||
"ang": 0x2220,
|
||||
"and": 0x2227,
|
||||
"or": 0x2228,
|
||||
"cap": 0x2229,
|
||||
"cup": 0x222A,
|
||||
"int": 0x222B,
|
||||
"there4": 0x2234,
|
||||
"sim": 0x223C,
|
||||
"cong": 0x2245,
|
||||
"asymp": 0x2248,
|
||||
"ne": 0x2260,
|
||||
"equiv": 0x2261,
|
||||
"le": 0x2264,
|
||||
"ge": 0x2265,
|
||||
"sub": 0x2282,
|
||||
"sup": 0x2283,
|
||||
"nsub": 0x2284,
|
||||
"sube": 0x2286,
|
||||
"supe": 0x2287,
|
||||
"oplus": 0x2295,
|
||||
"otimes": 0x2297,
|
||||
"perp": 0x22A5,
|
||||
"sdot": 0x22C5,
|
||||
"lceil": 0x2308,
|
||||
"rceil": 0x2309,
|
||||
"lfloor": 0x230A,
|
||||
"rfloor": 0x230B,
|
||||
"lang": 0x2329,
|
||||
"rang": 0x232A,
|
||||
"loz": 0x25CA,
|
||||
"spades": 0x2660,
|
||||
"clubs": 0x2663,
|
||||
"hearts": 0x2665,
|
||||
"diams": 0x2666
|
||||
});
|
||||
const entities = createMap<number>({
|
||||
"quot": 0x0022,
|
||||
"amp": 0x0026,
|
||||
"apos": 0x0027,
|
||||
"lt": 0x003C,
|
||||
"gt": 0x003E,
|
||||
"nbsp": 0x00A0,
|
||||
"iexcl": 0x00A1,
|
||||
"cent": 0x00A2,
|
||||
"pound": 0x00A3,
|
||||
"curren": 0x00A4,
|
||||
"yen": 0x00A5,
|
||||
"brvbar": 0x00A6,
|
||||
"sect": 0x00A7,
|
||||
"uml": 0x00A8,
|
||||
"copy": 0x00A9,
|
||||
"ordf": 0x00AA,
|
||||
"laquo": 0x00AB,
|
||||
"not": 0x00AC,
|
||||
"shy": 0x00AD,
|
||||
"reg": 0x00AE,
|
||||
"macr": 0x00AF,
|
||||
"deg": 0x00B0,
|
||||
"plusmn": 0x00B1,
|
||||
"sup2": 0x00B2,
|
||||
"sup3": 0x00B3,
|
||||
"acute": 0x00B4,
|
||||
"micro": 0x00B5,
|
||||
"para": 0x00B6,
|
||||
"middot": 0x00B7,
|
||||
"cedil": 0x00B8,
|
||||
"sup1": 0x00B9,
|
||||
"ordm": 0x00BA,
|
||||
"raquo": 0x00BB,
|
||||
"frac14": 0x00BC,
|
||||
"frac12": 0x00BD,
|
||||
"frac34": 0x00BE,
|
||||
"iquest": 0x00BF,
|
||||
"Agrave": 0x00C0,
|
||||
"Aacute": 0x00C1,
|
||||
"Acirc": 0x00C2,
|
||||
"Atilde": 0x00C3,
|
||||
"Auml": 0x00C4,
|
||||
"Aring": 0x00C5,
|
||||
"AElig": 0x00C6,
|
||||
"Ccedil": 0x00C7,
|
||||
"Egrave": 0x00C8,
|
||||
"Eacute": 0x00C9,
|
||||
"Ecirc": 0x00CA,
|
||||
"Euml": 0x00CB,
|
||||
"Igrave": 0x00CC,
|
||||
"Iacute": 0x00CD,
|
||||
"Icirc": 0x00CE,
|
||||
"Iuml": 0x00CF,
|
||||
"ETH": 0x00D0,
|
||||
"Ntilde": 0x00D1,
|
||||
"Ograve": 0x00D2,
|
||||
"Oacute": 0x00D3,
|
||||
"Ocirc": 0x00D4,
|
||||
"Otilde": 0x00D5,
|
||||
"Ouml": 0x00D6,
|
||||
"times": 0x00D7,
|
||||
"Oslash": 0x00D8,
|
||||
"Ugrave": 0x00D9,
|
||||
"Uacute": 0x00DA,
|
||||
"Ucirc": 0x00DB,
|
||||
"Uuml": 0x00DC,
|
||||
"Yacute": 0x00DD,
|
||||
"THORN": 0x00DE,
|
||||
"szlig": 0x00DF,
|
||||
"agrave": 0x00E0,
|
||||
"aacute": 0x00E1,
|
||||
"acirc": 0x00E2,
|
||||
"atilde": 0x00E3,
|
||||
"auml": 0x00E4,
|
||||
"aring": 0x00E5,
|
||||
"aelig": 0x00E6,
|
||||
"ccedil": 0x00E7,
|
||||
"egrave": 0x00E8,
|
||||
"eacute": 0x00E9,
|
||||
"ecirc": 0x00EA,
|
||||
"euml": 0x00EB,
|
||||
"igrave": 0x00EC,
|
||||
"iacute": 0x00ED,
|
||||
"icirc": 0x00EE,
|
||||
"iuml": 0x00EF,
|
||||
"eth": 0x00F0,
|
||||
"ntilde": 0x00F1,
|
||||
"ograve": 0x00F2,
|
||||
"oacute": 0x00F3,
|
||||
"ocirc": 0x00F4,
|
||||
"otilde": 0x00F5,
|
||||
"ouml": 0x00F6,
|
||||
"divide": 0x00F7,
|
||||
"oslash": 0x00F8,
|
||||
"ugrave": 0x00F9,
|
||||
"uacute": 0x00FA,
|
||||
"ucirc": 0x00FB,
|
||||
"uuml": 0x00FC,
|
||||
"yacute": 0x00FD,
|
||||
"thorn": 0x00FE,
|
||||
"yuml": 0x00FF,
|
||||
"OElig": 0x0152,
|
||||
"oelig": 0x0153,
|
||||
"Scaron": 0x0160,
|
||||
"scaron": 0x0161,
|
||||
"Yuml": 0x0178,
|
||||
"fnof": 0x0192,
|
||||
"circ": 0x02C6,
|
||||
"tilde": 0x02DC,
|
||||
"Alpha": 0x0391,
|
||||
"Beta": 0x0392,
|
||||
"Gamma": 0x0393,
|
||||
"Delta": 0x0394,
|
||||
"Epsilon": 0x0395,
|
||||
"Zeta": 0x0396,
|
||||
"Eta": 0x0397,
|
||||
"Theta": 0x0398,
|
||||
"Iota": 0x0399,
|
||||
"Kappa": 0x039A,
|
||||
"Lambda": 0x039B,
|
||||
"Mu": 0x039C,
|
||||
"Nu": 0x039D,
|
||||
"Xi": 0x039E,
|
||||
"Omicron": 0x039F,
|
||||
"Pi": 0x03A0,
|
||||
"Rho": 0x03A1,
|
||||
"Sigma": 0x03A3,
|
||||
"Tau": 0x03A4,
|
||||
"Upsilon": 0x03A5,
|
||||
"Phi": 0x03A6,
|
||||
"Chi": 0x03A7,
|
||||
"Psi": 0x03A8,
|
||||
"Omega": 0x03A9,
|
||||
"alpha": 0x03B1,
|
||||
"beta": 0x03B2,
|
||||
"gamma": 0x03B3,
|
||||
"delta": 0x03B4,
|
||||
"epsilon": 0x03B5,
|
||||
"zeta": 0x03B6,
|
||||
"eta": 0x03B7,
|
||||
"theta": 0x03B8,
|
||||
"iota": 0x03B9,
|
||||
"kappa": 0x03BA,
|
||||
"lambda": 0x03BB,
|
||||
"mu": 0x03BC,
|
||||
"nu": 0x03BD,
|
||||
"xi": 0x03BE,
|
||||
"omicron": 0x03BF,
|
||||
"pi": 0x03C0,
|
||||
"rho": 0x03C1,
|
||||
"sigmaf": 0x03C2,
|
||||
"sigma": 0x03C3,
|
||||
"tau": 0x03C4,
|
||||
"upsilon": 0x03C5,
|
||||
"phi": 0x03C6,
|
||||
"chi": 0x03C7,
|
||||
"psi": 0x03C8,
|
||||
"omega": 0x03C9,
|
||||
"thetasym": 0x03D1,
|
||||
"upsih": 0x03D2,
|
||||
"piv": 0x03D6,
|
||||
"ensp": 0x2002,
|
||||
"emsp": 0x2003,
|
||||
"thinsp": 0x2009,
|
||||
"zwnj": 0x200C,
|
||||
"zwj": 0x200D,
|
||||
"lrm": 0x200E,
|
||||
"rlm": 0x200F,
|
||||
"ndash": 0x2013,
|
||||
"mdash": 0x2014,
|
||||
"lsquo": 0x2018,
|
||||
"rsquo": 0x2019,
|
||||
"sbquo": 0x201A,
|
||||
"ldquo": 0x201C,
|
||||
"rdquo": 0x201D,
|
||||
"bdquo": 0x201E,
|
||||
"dagger": 0x2020,
|
||||
"Dagger": 0x2021,
|
||||
"bull": 0x2022,
|
||||
"hellip": 0x2026,
|
||||
"permil": 0x2030,
|
||||
"prime": 0x2032,
|
||||
"Prime": 0x2033,
|
||||
"lsaquo": 0x2039,
|
||||
"rsaquo": 0x203A,
|
||||
"oline": 0x203E,
|
||||
"frasl": 0x2044,
|
||||
"euro": 0x20AC,
|
||||
"image": 0x2111,
|
||||
"weierp": 0x2118,
|
||||
"real": 0x211C,
|
||||
"trade": 0x2122,
|
||||
"alefsym": 0x2135,
|
||||
"larr": 0x2190,
|
||||
"uarr": 0x2191,
|
||||
"rarr": 0x2192,
|
||||
"darr": 0x2193,
|
||||
"harr": 0x2194,
|
||||
"crarr": 0x21B5,
|
||||
"lArr": 0x21D0,
|
||||
"uArr": 0x21D1,
|
||||
"rArr": 0x21D2,
|
||||
"dArr": 0x21D3,
|
||||
"hArr": 0x21D4,
|
||||
"forall": 0x2200,
|
||||
"part": 0x2202,
|
||||
"exist": 0x2203,
|
||||
"empty": 0x2205,
|
||||
"nabla": 0x2207,
|
||||
"isin": 0x2208,
|
||||
"notin": 0x2209,
|
||||
"ni": 0x220B,
|
||||
"prod": 0x220F,
|
||||
"sum": 0x2211,
|
||||
"minus": 0x2212,
|
||||
"lowast": 0x2217,
|
||||
"radic": 0x221A,
|
||||
"prop": 0x221D,
|
||||
"infin": 0x221E,
|
||||
"ang": 0x2220,
|
||||
"and": 0x2227,
|
||||
"or": 0x2228,
|
||||
"cap": 0x2229,
|
||||
"cup": 0x222A,
|
||||
"int": 0x222B,
|
||||
"there4": 0x2234,
|
||||
"sim": 0x223C,
|
||||
"cong": 0x2245,
|
||||
"asymp": 0x2248,
|
||||
"ne": 0x2260,
|
||||
"equiv": 0x2261,
|
||||
"le": 0x2264,
|
||||
"ge": 0x2265,
|
||||
"sub": 0x2282,
|
||||
"sup": 0x2283,
|
||||
"nsub": 0x2284,
|
||||
"sube": 0x2286,
|
||||
"supe": 0x2287,
|
||||
"oplus": 0x2295,
|
||||
"otimes": 0x2297,
|
||||
"perp": 0x22A5,
|
||||
"sdot": 0x22C5,
|
||||
"lceil": 0x2308,
|
||||
"rceil": 0x2309,
|
||||
"lfloor": 0x230A,
|
||||
"rfloor": 0x230B,
|
||||
"lang": 0x2329,
|
||||
"rang": 0x232A,
|
||||
"loz": 0x25CA,
|
||||
"spades": 0x2660,
|
||||
"clubs": 0x2663,
|
||||
"hearts": 0x2665,
|
||||
"diams": 0x2666
|
||||
});
|
||||
|
||||
function createAssignHelper(helperState: EmitHelperState, attributesSegments: Expression[]) {
|
||||
requestEmitHelper(helperState, assignHelper);
|
||||
return createCall(
|
||||
getHelperName(helperState, "__assign"),
|
||||
/*typeArguments*/ undefined,
|
||||
attributesSegments
|
||||
);
|
||||
}
|
||||
|
||||
const assignHelper: EmitHelper = {
|
||||
name: "typescript:assign",
|
||||
scoped: false,
|
||||
priority: 1,
|
||||
text: `
|
||||
var __assign = (this && this.__assign) || Object.assign || function(t) {
|
||||
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
||||
s = arguments[i];
|
||||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
||||
t[p] = s[p];
|
||||
}
|
||||
return t;
|
||||
};`
|
||||
};
|
||||
}
|
||||
@@ -13,7 +13,27 @@ namespace ts {
|
||||
}
|
||||
|
||||
if (isExternalModule(node) || compilerOptions.isolatedModules) {
|
||||
return visitEachChild(node, visitor, context);
|
||||
const externalHelpersModuleName = getExternalHelpersModuleName(node);
|
||||
if (externalHelpersModuleName) {
|
||||
const statements: Statement[] = [];
|
||||
const statementOffset = addPrologueDirectives(statements, node.statements);
|
||||
append(statements,
|
||||
createImportDeclaration(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
createImportClause(/*name*/ undefined, createNamespaceImport(externalHelpersModuleName)),
|
||||
createLiteral(externalHelpersModuleNameText)
|
||||
)
|
||||
);
|
||||
|
||||
addRange(statements, visitNodes(node.statements, visitor, isStatement, statementOffset));
|
||||
return updateSourceFileNode(
|
||||
node,
|
||||
createNodeArray(statements, node.statements));
|
||||
}
|
||||
else {
|
||||
return visitEachChild(node, visitor, context);
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
|
||||
@@ -82,13 +82,14 @@ namespace ts {
|
||||
|
||||
const statements: Statement[] = [];
|
||||
const statementOffset = addPrologueDirectives(statements, node.statements, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict, sourceElementVisitor);
|
||||
append(statements, visitNode(currentModuleInfo.externalHelpersImportDeclaration, sourceElementVisitor, isStatement, /*optional*/ true));
|
||||
addRange(statements, visitNodes(node.statements, sourceElementVisitor, isStatement, statementOffset));
|
||||
addRange(statements, endLexicalEnvironment());
|
||||
addExportEqualsIfNeeded(statements, /*emitAsReturn*/ false);
|
||||
|
||||
const updated = updateSourceFileNode(node, createNodeArray(statements, node.statements));
|
||||
if (currentModuleInfo.hasExportStarsToExportValues) {
|
||||
setEmitFlags(updated, EmitFlags.EmitExportStar | getEmitFlags(node));
|
||||
addEmitHelper(updated, exportStarHelper);
|
||||
}
|
||||
|
||||
return updated;
|
||||
@@ -257,6 +258,7 @@ namespace ts {
|
||||
const statementOffset = addPrologueDirectives(statements, node.statements, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict, sourceElementVisitor);
|
||||
|
||||
// Visit each statement of the module body.
|
||||
append(statements, visitNode(currentModuleInfo.externalHelpersImportDeclaration, sourceElementVisitor, isStatement, /*optional*/ true));
|
||||
addRange(statements, visitNodes(node.statements, sourceElementVisitor, isStatement, statementOffset));
|
||||
|
||||
// End the lexical environment for the module body
|
||||
@@ -270,7 +272,7 @@ namespace ts {
|
||||
if (currentModuleInfo.hasExportStarsToExportValues) {
|
||||
// If we have any `export * from ...` declarations
|
||||
// we need to inform the emitter to add the __export helper.
|
||||
setEmitFlags(body, EmitFlags.EmitExportStar);
|
||||
addEmitHelper(body, exportStarHelper);
|
||||
}
|
||||
|
||||
return body;
|
||||
@@ -1312,4 +1314,14 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// emit output for the __export helper function
|
||||
const exportStarHelper: EmitHelper = {
|
||||
name: "typescript:export-star",
|
||||
scoped: true,
|
||||
text: `
|
||||
function __export(m) {
|
||||
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
|
||||
}`
|
||||
};
|
||||
}
|
||||
|
||||
@@ -82,6 +82,7 @@ namespace ts {
|
||||
|
||||
// Add the body of the module.
|
||||
const dependencyGroups = collectDependencyGroups(moduleInfo.externalImports);
|
||||
const moduleBodyBlock = createSystemModuleBody(node, dependencyGroups);
|
||||
const moduleBodyFunction = createFunctionExpression(
|
||||
/*modifiers*/ undefined,
|
||||
/*asteriskToken*/ undefined,
|
||||
@@ -92,7 +93,7 @@ namespace ts {
|
||||
createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, contextObject)
|
||||
],
|
||||
/*type*/ undefined,
|
||||
createSystemModuleBody(node, dependencyGroups)
|
||||
moduleBodyBlock
|
||||
);
|
||||
|
||||
// Write the call to `System.register`
|
||||
@@ -115,7 +116,9 @@ namespace ts {
|
||||
], node.statements)
|
||||
);
|
||||
|
||||
setEmitFlags(updated, getEmitFlags(node) & ~EmitFlags.EmitEmitHelpers);
|
||||
if (!(compilerOptions.outFile || compilerOptions.out)) {
|
||||
moveEmitHelpers(updated, moduleBodyBlock, helper => !helper.scoped);
|
||||
}
|
||||
|
||||
if (noSubstitution) {
|
||||
noSubstitutionMap[id] = noSubstitution;
|
||||
@@ -236,6 +239,9 @@ namespace ts {
|
||||
)
|
||||
);
|
||||
|
||||
// Visit the synthetic external helpers import declaration if present
|
||||
visitNode(moduleInfo.externalHelpersImportDeclaration, sourceElementVisitor, isStatement, /*optional*/ true);
|
||||
|
||||
// Visit the statements of the source file, emitting any transformations into
|
||||
// the `executeStatements` array. We do this *before* we fill the `setters` array
|
||||
// as we both emit transformations as well as aggregate some data used when creating
|
||||
@@ -280,9 +286,7 @@ namespace ts {
|
||||
)
|
||||
);
|
||||
|
||||
const body = createBlock(statements, /*location*/ undefined, /*multiLine*/ true);
|
||||
setEmitFlags(body, EmitFlags.EmitEmitHelpers);
|
||||
return body;
|
||||
return createBlock(statements, /*location*/ undefined, /*multiLine*/ true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -394,7 +398,13 @@ namespace ts {
|
||||
if (localNames) {
|
||||
condition = createLogicalAnd(
|
||||
condition,
|
||||
createLogicalNot(createHasOwnProperty(localNames, n))
|
||||
createLogicalNot(
|
||||
createCall(
|
||||
createPropertyAccess(localNames, "hasOwnProperty"),
|
||||
/*typeArguments*/ undefined,
|
||||
[n]
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace ts {
|
||||
let currentNamespaceContainerName: Identifier;
|
||||
let currentScope: SourceFile | Block | ModuleBlock | CaseBlock;
|
||||
let currentScopeFirstDeclarationsOfName: Map<Node>;
|
||||
let currentExternalHelpersModuleName: Identifier;
|
||||
let helperState: EmitHelperState;
|
||||
|
||||
/**
|
||||
* Keeps track of whether expression substitution has been enabled for specific edge cases.
|
||||
@@ -80,7 +80,23 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
return visitNode(node, visitor, isSourceFile);
|
||||
currentSourceFile = node;
|
||||
currentScope = node;
|
||||
currentScopeFirstDeclarationsOfName = createMap<Node>();
|
||||
helperState = { currentSourceFile, compilerOptions };
|
||||
|
||||
let visited = visitEachChild(node, sourceElementVisitor, context);
|
||||
if (compilerOptions.alwaysStrict) {
|
||||
visited = updateSourceFileNode(visited, ensureUseStrict(visited.statements));
|
||||
}
|
||||
|
||||
addEmitHelpers(visited, helperState.requestedHelpers);
|
||||
|
||||
currentSourceFile = undefined;
|
||||
currentScope = undefined;
|
||||
currentScopeFirstDeclarationsOfName = undefined;
|
||||
helperState = undefined;
|
||||
return visited;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -122,10 +138,7 @@ namespace ts {
|
||||
* @param node The node to visit.
|
||||
*/
|
||||
function visitorWorker(node: Node): VisitResult<Node> {
|
||||
if (node.kind === SyntaxKind.SourceFile) {
|
||||
return visitSourceFile(<SourceFile>node);
|
||||
}
|
||||
else if (node.transformFlags & TransformFlags.TypeScript) {
|
||||
if (node.transformFlags & TransformFlags.TypeScript) {
|
||||
// This node is explicitly marked as TypeScript, so we should transform the node.
|
||||
return visitTypeScript(node);
|
||||
}
|
||||
@@ -252,7 +265,6 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Branching visitor, visits a TypeScript syntax node.
|
||||
*
|
||||
@@ -446,7 +458,6 @@ namespace ts {
|
||||
*/
|
||||
function onBeforeVisitNode(node: Node) {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.SourceFile:
|
||||
case SyntaxKind.CaseBlock:
|
||||
case SyntaxKind.ModuleBlock:
|
||||
case SyntaxKind.Block:
|
||||
@@ -465,50 +476,6 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function visitSourceFile(node: SourceFile) {
|
||||
currentSourceFile = node;
|
||||
|
||||
// ensure "use strict" is emitted in all scenarios in alwaysStrict mode
|
||||
if (compilerOptions.alwaysStrict) {
|
||||
node = ensureUseStrict(node);
|
||||
}
|
||||
|
||||
// If the source file requires any helpers and is an external module, and
|
||||
// the importHelpers compiler option is enabled, emit a synthesized import
|
||||
// statement for the helpers library.
|
||||
if (node.flags & NodeFlags.EmitHelperFlags
|
||||
&& compilerOptions.importHelpers
|
||||
&& (isExternalModule(node) || compilerOptions.isolatedModules)) {
|
||||
startLexicalEnvironment();
|
||||
const statements: Statement[] = [];
|
||||
const statementOffset = addPrologueDirectives(statements, node.statements, /*ensureUseStrict*/ false, visitor);
|
||||
const externalHelpersModuleName = createUniqueName(externalHelpersModuleNameText);
|
||||
const externalHelpersModuleImport = createImportDeclaration(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
createImportClause(/*name*/ undefined, createNamespaceImport(externalHelpersModuleName)),
|
||||
createLiteral(externalHelpersModuleNameText));
|
||||
|
||||
externalHelpersModuleImport.parent = node;
|
||||
externalHelpersModuleImport.flags &= ~NodeFlags.Synthesized;
|
||||
statements.push(externalHelpersModuleImport);
|
||||
|
||||
currentExternalHelpersModuleName = externalHelpersModuleName;
|
||||
addRange(statements, visitNodes(node.statements, sourceElementVisitor, isStatement, statementOffset));
|
||||
addRange(statements, endLexicalEnvironment());
|
||||
currentExternalHelpersModuleName = undefined;
|
||||
|
||||
node = updateSourceFileNode(node, createNodeArray(statements, node.statements));
|
||||
node.externalHelpersModuleName = externalHelpersModuleName;
|
||||
}
|
||||
else {
|
||||
node = visitEachChild(node, sourceElementVisitor, context);
|
||||
}
|
||||
|
||||
setEmitFlags(node, EmitFlags.EmitEmitHelpers | getEmitFlags(node));
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether we should emit a __decorate call for a class declaration.
|
||||
*/
|
||||
@@ -1418,7 +1385,7 @@ namespace ts {
|
||||
: undefined;
|
||||
|
||||
const helper = createDecorateHelper(
|
||||
currentExternalHelpersModuleName,
|
||||
helperState,
|
||||
decoratorExpressions,
|
||||
prefix,
|
||||
memberName,
|
||||
@@ -1456,7 +1423,7 @@ namespace ts {
|
||||
|
||||
const classAlias = classAliases && classAliases[getOriginalNodeId(node)];
|
||||
const localName = getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true);
|
||||
const decorate = createDecorateHelper(currentExternalHelpersModuleName, decoratorExpressions, localName);
|
||||
const decorate = createDecorateHelper(helperState, decoratorExpressions, localName);
|
||||
const expression = createAssignment(localName, classAlias ? createAssignment(classAlias, decorate) : decorate);
|
||||
setEmitFlags(expression, EmitFlags.NoComments);
|
||||
setSourceMapRange(expression, moveRangePastDecorators(node));
|
||||
@@ -1484,7 +1451,7 @@ namespace ts {
|
||||
expressions = [];
|
||||
for (const decorator of decorators) {
|
||||
const helper = createParamHelper(
|
||||
currentExternalHelpersModuleName,
|
||||
helperState,
|
||||
transformDecorator(decorator),
|
||||
parameterOffset,
|
||||
/*location*/ decorator.expression);
|
||||
@@ -1514,13 +1481,13 @@ namespace ts {
|
||||
function addOldTypeMetadata(node: Declaration, decoratorExpressions: Expression[]) {
|
||||
if (compilerOptions.emitDecoratorMetadata) {
|
||||
if (shouldAddTypeMetadata(node)) {
|
||||
decoratorExpressions.push(createMetadataHelper(currentExternalHelpersModuleName, "design:type", serializeTypeOfNode(node)));
|
||||
decoratorExpressions.push(createMetadataHelper(helperState, "design:type", serializeTypeOfNode(node)));
|
||||
}
|
||||
if (shouldAddParamTypesMetadata(node)) {
|
||||
decoratorExpressions.push(createMetadataHelper(currentExternalHelpersModuleName, "design:paramtypes", serializeParameterTypesOfNode(node)));
|
||||
decoratorExpressions.push(createMetadataHelper(helperState, "design:paramtypes", serializeParameterTypesOfNode(node)));
|
||||
}
|
||||
if (shouldAddReturnTypeMetadata(node)) {
|
||||
decoratorExpressions.push(createMetadataHelper(currentExternalHelpersModuleName, "design:returntype", serializeReturnTypeOfNode(node)));
|
||||
decoratorExpressions.push(createMetadataHelper(helperState, "design:returntype", serializeReturnTypeOfNode(node)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1538,7 +1505,7 @@ namespace ts {
|
||||
(properties || (properties = [])).push(createPropertyAssignment("returnType", createArrowFunction(/*modifiers*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, createToken(SyntaxKind.EqualsGreaterThanToken), serializeReturnTypeOfNode(node))));
|
||||
}
|
||||
if (properties) {
|
||||
decoratorExpressions.push(createMetadataHelper(currentExternalHelpersModuleName, "design:typeinfo", createObjectLiteral(properties, /*location*/ undefined, /*multiLine*/ true)));
|
||||
decoratorExpressions.push(createMetadataHelper(helperState, "design:typeinfo", createObjectLiteral(properties, /*location*/ undefined, /*multiLine*/ true)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3404,4 +3371,77 @@ namespace ts {
|
||||
: undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function createParamHelper(helperState: EmitHelperState, expression: Expression, parameterOffset: number, location?: TextRange) {
|
||||
requestEmitHelper(helperState, paramHelper);
|
||||
return createCall(
|
||||
getHelperName(helperState, "__param"),
|
||||
/*typeArguments*/ undefined,
|
||||
[
|
||||
createLiteral(parameterOffset),
|
||||
expression
|
||||
],
|
||||
location
|
||||
);
|
||||
}
|
||||
|
||||
function createMetadataHelper(helperState: EmitHelperState, metadataKey: string, metadataValue: Expression) {
|
||||
requestEmitHelper(helperState, metadataHelper);
|
||||
return createCall(
|
||||
getHelperName(helperState, "__metadata"),
|
||||
/*typeArguments*/ undefined,
|
||||
[
|
||||
createLiteral(metadataKey),
|
||||
metadataValue
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
function createDecorateHelper(helperState: EmitHelperState, decoratorExpressions: Expression[], target: Expression, memberName?: Expression, descriptor?: Expression, location?: TextRange) {
|
||||
const argumentsArray: Expression[] = [];
|
||||
argumentsArray.push(createArrayLiteral(decoratorExpressions, /*location*/ undefined, /*multiLine*/ true));
|
||||
argumentsArray.push(target);
|
||||
if (memberName) {
|
||||
argumentsArray.push(memberName);
|
||||
if (descriptor) {
|
||||
argumentsArray.push(descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
requestEmitHelper(helperState, decorateHelper);
|
||||
return createCall(getHelperName(helperState, "__decorate"), /*typeArguments*/ undefined, argumentsArray, location);
|
||||
}
|
||||
|
||||
const decorateHelper: EmitHelper = {
|
||||
name: "typescript:decorate",
|
||||
scoped: false,
|
||||
priority: 2,
|
||||
text: `
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};`
|
||||
};
|
||||
|
||||
const metadataHelper: EmitHelper = {
|
||||
name: "typescript:metadata",
|
||||
scoped: false,
|
||||
priority: 3,
|
||||
text: `
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};`
|
||||
};
|
||||
|
||||
const paramHelper: EmitHelper = {
|
||||
name: "typescript:param",
|
||||
scoped: false,
|
||||
priority: 4,
|
||||
text: `
|
||||
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
||||
return function (target, key) { decorator(target, key, paramIndex); }
|
||||
};`
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2088,8 +2088,6 @@ namespace ts {
|
||||
/* @internal */ imports: LiteralExpression[];
|
||||
/* @internal */ moduleAugmentations: LiteralExpression[];
|
||||
/* @internal */ patternAmbientModules?: PatternAmbientModule[];
|
||||
// The synthesized identifier for an imported external helpers module.
|
||||
/* @internal */ externalHelpersModuleName?: Identifier;
|
||||
}
|
||||
|
||||
export interface ScriptReferenceHost {
|
||||
@@ -3476,20 +3474,18 @@ namespace ts {
|
||||
|
||||
/* @internal */
|
||||
export interface EmitNode {
|
||||
flags?: EmitFlags;
|
||||
commentRange?: TextRange;
|
||||
sourceMapRange?: TextRange;
|
||||
tokenSourceMapRanges?: Map<TextRange>;
|
||||
annotatedNodes?: Node[]; // Tracks Parse-tree nodes with EmitNodes for eventual cleanup.
|
||||
constantValue?: number;
|
||||
flags?: EmitFlags; // Flags that customize emit
|
||||
commentRange?: TextRange; // The text range to use when emitting leading or trailing comments
|
||||
sourceMapRange?: TextRange; // The text range to use when emitting leading or trailing source mappings
|
||||
tokenSourceMapRanges?: Map<TextRange>; // The text range to use when emitting source mappings for tokens
|
||||
constantValue?: number; // The constant value of an expression
|
||||
externalHelpersModuleName?: Identifier; // The local name for an imported helpers module
|
||||
helpers?: EmitHelper[]; // Emit helpers for the node
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export const enum EmitFlags {
|
||||
EmitEmitHelpers = 1 << 0, // Any emit helpers should be written to this node.
|
||||
EmitExportStar = 1 << 1, // The export * helper should be written to this node.
|
||||
EmitSuperHelper = 1 << 2, // Emit the basic _super helper for async methods.
|
||||
EmitAdvancedSuperHelper = 1 << 3, // Emit the advanced _super helper for async methods.
|
||||
UMDDefine = 1 << 4, // This node should be replaced with the UMD define helper.
|
||||
SingleLine = 1 << 5, // The contents of this node should be emitted on a single line.
|
||||
AdviseOnEmitNode = 1 << 6, // The printer should invoke the onEmitNode callback when printing this node.
|
||||
@@ -3517,6 +3513,14 @@ namespace ts {
|
||||
HasEndOfDeclarationMarker = 1 << 25, // Declaration has an associated NotEmittedStatement to mark the end of the declaration
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export interface EmitHelper {
|
||||
readonly name: string; // A unique name for this helper.
|
||||
readonly scoped: boolean; // Indicates whether ther helper MUST be emitted in the current scope.
|
||||
readonly text: string; // ES3-compatible raw script text.
|
||||
readonly priority?: number; // Helpers with a higher priority are emitted earlier than other helpers on the node.
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export const enum EmitContext {
|
||||
SourceFile, // Emitting a SourceFile
|
||||
|
||||
@@ -3493,153 +3493,6 @@ namespace ts {
|
||||
return positionIsSynthesized(range.pos) ? -1 : skipTrivia(sourceFile.text, range.pos);
|
||||
}
|
||||
|
||||
export interface ExternalModuleInfo {
|
||||
externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[]; // imports of other external modules
|
||||
exportSpecifiers: Map<ExportSpecifier[]>; // export specifiers by name
|
||||
exportedBindings: Map<Identifier[]>; // exported names of local declarations
|
||||
exportedNames: Identifier[]; // all exported names local to module
|
||||
exportEquals: ExportAssignment | undefined; // an export= declaration if one was present
|
||||
hasExportStarsToExportValues: boolean; // whether this module contains export*
|
||||
}
|
||||
|
||||
export function collectExternalModuleInfo(sourceFile: SourceFile, resolver: EmitResolver): ExternalModuleInfo {
|
||||
const externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[] = [];
|
||||
const exportSpecifiers = createMap<ExportSpecifier[]>();
|
||||
const exportedBindings = createMap<Identifier[]>();
|
||||
const uniqueExports = createMap<Identifier>();
|
||||
let hasExportDefault = false;
|
||||
let exportEquals: ExportAssignment = undefined;
|
||||
let hasExportStarsToExportValues = false;
|
||||
for (const node of sourceFile.statements) {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ImportDeclaration:
|
||||
// import "mod"
|
||||
// import x from "mod"
|
||||
// import * as x from "mod"
|
||||
// import { x, y } from "mod"
|
||||
externalImports.push(<ImportDeclaration>node);
|
||||
break;
|
||||
|
||||
case SyntaxKind.ImportEqualsDeclaration:
|
||||
if ((<ImportEqualsDeclaration>node).moduleReference.kind === SyntaxKind.ExternalModuleReference) {
|
||||
// import x = require("mod")
|
||||
externalImports.push(<ImportEqualsDeclaration>node);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SyntaxKind.ExportDeclaration:
|
||||
if ((<ExportDeclaration>node).moduleSpecifier) {
|
||||
if (!(<ExportDeclaration>node).exportClause) {
|
||||
// export * from "mod"
|
||||
externalImports.push(<ExportDeclaration>node);
|
||||
hasExportStarsToExportValues = true;
|
||||
}
|
||||
else {
|
||||
// export { x, y } from "mod"
|
||||
externalImports.push(<ExportDeclaration>node);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// export { x, y }
|
||||
for (const specifier of (<ExportDeclaration>node).exportClause.elements) {
|
||||
if (!uniqueExports[specifier.name.text]) {
|
||||
const name = specifier.propertyName || specifier.name;
|
||||
multiMapAdd(exportSpecifiers, name.text, specifier);
|
||||
|
||||
const decl = resolver.getReferencedImportDeclaration(name)
|
||||
|| resolver.getReferencedValueDeclaration(name);
|
||||
|
||||
if (decl) {
|
||||
multiMapAdd(exportedBindings, getOriginalNodeId(decl), specifier.name);
|
||||
}
|
||||
|
||||
uniqueExports[specifier.name.text] = specifier.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SyntaxKind.ExportAssignment:
|
||||
if ((<ExportAssignment>node).isExportEquals && !exportEquals) {
|
||||
// export = x
|
||||
exportEquals = <ExportAssignment>node;
|
||||
}
|
||||
break;
|
||||
|
||||
case SyntaxKind.VariableStatement:
|
||||
if (hasModifier(node, ModifierFlags.Export)) {
|
||||
for (const decl of (<VariableStatement>node).declarationList.declarations) {
|
||||
collectExportedVariableInfo(decl, uniqueExports);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
if (hasModifier(node, ModifierFlags.Export)) {
|
||||
if (hasModifier(node, ModifierFlags.Default)) {
|
||||
// export default function() { }
|
||||
if (!hasExportDefault) {
|
||||
multiMapAdd(exportedBindings, getOriginalNodeId(node), getDeclarationName(<FunctionDeclaration>node));
|
||||
hasExportDefault = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// export function x() { }
|
||||
const name = (<FunctionDeclaration>node).name;
|
||||
if (!uniqueExports[name.text]) {
|
||||
multiMapAdd(exportedBindings, getOriginalNodeId(node), name);
|
||||
uniqueExports[name.text] = name;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
if (hasModifier(node, ModifierFlags.Export)) {
|
||||
if (hasModifier(node, ModifierFlags.Default)) {
|
||||
// export default class { }
|
||||
if (!hasExportDefault) {
|
||||
multiMapAdd(exportedBindings, getOriginalNodeId(node), getDeclarationName(<ClassDeclaration>node));
|
||||
hasExportDefault = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// export class x { }
|
||||
const name = (<ClassDeclaration>node).name;
|
||||
if (!uniqueExports[name.text]) {
|
||||
multiMapAdd(exportedBindings, getOriginalNodeId(node), name);
|
||||
uniqueExports[name.text] = name;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let exportedNames: Identifier[];
|
||||
for (const key in uniqueExports) {
|
||||
exportedNames = ts.append(exportedNames, uniqueExports[key]);
|
||||
}
|
||||
|
||||
return { externalImports, exportSpecifiers, exportEquals, hasExportStarsToExportValues, exportedBindings, exportedNames };
|
||||
}
|
||||
|
||||
function collectExportedVariableInfo(decl: VariableDeclaration | BindingElement, uniqueExports: Map<Identifier>) {
|
||||
if (isBindingPattern(decl.name)) {
|
||||
for (const element of decl.name.elements) {
|
||||
if (!isOmittedExpression(element)) {
|
||||
collectExportedVariableInfo(element, uniqueExports);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!isGeneratedIdentifier(decl.name)) {
|
||||
if (!uniqueExports[decl.name.text]) {
|
||||
uniqueExports[decl.name.text] = decl.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a name was originally the declaration name of an enum or namespace
|
||||
* declaration.
|
||||
|
||||
Reference in New Issue
Block a user