• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1import {
2    __String, ArrayLiteralExpression, arrayToMap, BindingOrAssignmentElement, Block, compareValues, Comparison,
3    createExpressionFromEntityName, Debug, EmitFlags, EmitHelper, EmitHelperUniqueNameCallback, EmitNode, EntityName,
4    Expression, FunctionExpression, GeneratedIdentifierFlags, getEmitFlags, getEmitScriptTarget,
5    getPropertyNameOfBindingOrAssignmentElement, Identifier, isCallExpression, isComputedPropertyName, isIdentifier,
6    memoize, PrivateIdentifierKind, ReadonlyESMap, ScriptTarget, setEmitFlags, setTextRange, SyntaxKind, TextRange,
7    TransformationContext, UnscopedEmitHelper,
8} from "../_namespaces/ts";
9
10/** @internal */
11export interface EmitHelperFactory {
12    getUnscopedHelperName(name: string): Identifier;
13    // TypeScript Helpers
14    createDecorateHelper(decoratorExpressions: readonly Expression[], target: Expression, memberName?: Expression, descriptor?: Expression): Expression;
15    createMetadataHelper(metadataKey: string, metadataValue: Expression): Expression;
16    createParamHelper(expression: Expression, parameterOffset: number): Expression;
17    // ES2018 Helpers
18    createAssignHelper(attributesSegments: readonly Expression[]): Expression;
19    createAwaitHelper(expression: Expression): Expression;
20    createAsyncGeneratorHelper(generatorFunc: FunctionExpression, hasLexicalThis: boolean): Expression;
21    createAsyncDelegatorHelper(expression: Expression): Expression;
22    createAsyncValuesHelper(expression: Expression): Expression;
23    // ES2018 Destructuring Helpers
24    createRestHelper(value: Expression, elements: readonly BindingOrAssignmentElement[], computedTempVariables: readonly Expression[] | undefined, location: TextRange): Expression;
25    // ES2017 Helpers
26    createAwaiterHelper(hasLexicalThis: boolean, hasLexicalArguments: boolean, promiseConstructor: EntityName | Expression | undefined, body: Block): Expression;
27    // ES2015 Helpers
28    createExtendsHelper(name: Identifier): Expression;
29    createTemplateObjectHelper(cooked: ArrayLiteralExpression, raw: ArrayLiteralExpression): Expression;
30    createSpreadArrayHelper(to: Expression, from: Expression, packFrom: boolean): Expression;
31    // ES2015 Destructuring Helpers
32    createValuesHelper(expression: Expression): Expression;
33    createReadHelper(iteratorRecord: Expression, count: number | undefined): Expression;
34    // ES2015 Generator Helpers
35    createGeneratorHelper(body: FunctionExpression): Expression;
36    // ES Module Helpers
37    createCreateBindingHelper(module: Expression, inputName: Expression, outputName: Expression | undefined): Expression;
38    createImportStarHelper(expression: Expression): Expression;
39    createImportStarCallbackHelper(): Expression;
40    createImportDefaultHelper(expression: Expression): Expression;
41    createExportStarHelper(moduleExpression: Expression, exportsExpression?: Expression): Expression;
42    // Class Fields Helpers
43    createClassPrivateFieldGetHelper(receiver: Expression, state: Identifier, kind: PrivateIdentifierKind, f: Identifier | undefined): Expression;
44    createClassPrivateFieldSetHelper(receiver: Expression, state: Identifier, value: Expression, kind: PrivateIdentifierKind, f: Identifier | undefined): Expression;
45    createClassPrivateFieldInHelper(state: Identifier, receiver: Expression): Expression;
46}
47
48/** @internal */
49export function createEmitHelperFactory(context: TransformationContext): EmitHelperFactory {
50    const factory = context.factory;
51    const immutableTrue = memoize(() => setEmitFlags(factory.createTrue(), EmitFlags.Immutable));
52    const immutableFalse = memoize(() => setEmitFlags(factory.createFalse(), EmitFlags.Immutable));
53
54    return {
55        getUnscopedHelperName,
56        // TypeScript Helpers
57        createDecorateHelper,
58        createMetadataHelper,
59        createParamHelper,
60        // ES2018 Helpers
61        createAssignHelper,
62        createAwaitHelper,
63        createAsyncGeneratorHelper,
64        createAsyncDelegatorHelper,
65        createAsyncValuesHelper,
66        // ES2018 Destructuring Helpers
67        createRestHelper,
68        // ES2017 Helpers
69        createAwaiterHelper,
70        // ES2015 Helpers
71        createExtendsHelper,
72        createTemplateObjectHelper,
73        createSpreadArrayHelper,
74        // ES2015 Destructuring Helpers
75        createValuesHelper,
76        createReadHelper,
77        // ES2015 Generator Helpers
78        createGeneratorHelper,
79        // ES Module Helpers
80        createCreateBindingHelper,
81        createImportStarHelper,
82        createImportStarCallbackHelper,
83        createImportDefaultHelper,
84        createExportStarHelper,
85        // Class Fields Helpers
86        createClassPrivateFieldGetHelper,
87        createClassPrivateFieldSetHelper,
88        createClassPrivateFieldInHelper
89    };
90
91    /**
92     * Gets an identifier for the name of an *unscoped* emit helper.
93     */
94    function getUnscopedHelperName(name: string) {
95        return setEmitFlags(factory.createIdentifier(name), EmitFlags.HelperName | EmitFlags.AdviseOnEmitNode);
96    }
97
98    // TypeScript Helpers
99
100    function createDecorateHelper(decoratorExpressions: Expression[], target: Expression, memberName?: Expression, descriptor?: Expression) {
101        context.requestEmitHelper(decorateHelper);
102
103        const argumentsArray: Expression[] = [];
104        argumentsArray.push(factory.createArrayLiteralExpression(decoratorExpressions, /*multiLine*/ true));
105        argumentsArray.push(target);
106        if (memberName) {
107            argumentsArray.push(memberName);
108            if (descriptor) {
109                argumentsArray.push(descriptor);
110            }
111        }
112
113        return factory.createCallExpression(
114            getUnscopedHelperName("__decorate"),
115            /*typeArguments*/ undefined,
116            argumentsArray
117        );
118    }
119
120    function createMetadataHelper(metadataKey: string, metadataValue: Expression) {
121        context.requestEmitHelper(metadataHelper);
122        return factory.createCallExpression(
123            getUnscopedHelperName("__metadata"),
124            /*typeArguments*/ undefined,
125            [
126                factory.createStringLiteral(metadataKey),
127                metadataValue
128            ]
129        );
130    }
131
132    function createParamHelper(expression: Expression, parameterOffset: number, location?: TextRange) {
133        context.requestEmitHelper(paramHelper);
134        return setTextRange(
135            factory.createCallExpression(
136                getUnscopedHelperName("__param"),
137                /*typeArguments*/ undefined,
138                [
139                    factory.createNumericLiteral(parameterOffset + ""),
140                    expression
141                ]
142            ),
143            location
144        );
145    }
146
147    // ES2018 Helpers
148
149    function createAssignHelper(attributesSegments: Expression[]) {
150        if (getEmitScriptTarget(context.getCompilerOptions()) >= ScriptTarget.ES2015) {
151            return factory.createCallExpression(factory.createPropertyAccessExpression(factory.createIdentifier("Object"), "assign"),
152                              /*typeArguments*/ undefined,
153                              attributesSegments);
154        }
155        context.requestEmitHelper(assignHelper);
156        return factory.createCallExpression(
157            getUnscopedHelperName("__assign"),
158            /*typeArguments*/ undefined,
159            attributesSegments
160        );
161    }
162
163    function createAwaitHelper(expression: Expression) {
164        context.requestEmitHelper(awaitHelper);
165        return factory.createCallExpression(getUnscopedHelperName("__await"), /*typeArguments*/ undefined, [expression]);
166    }
167
168    function createAsyncGeneratorHelper(generatorFunc: FunctionExpression, hasLexicalThis: boolean) {
169        context.requestEmitHelper(awaitHelper);
170        context.requestEmitHelper(asyncGeneratorHelper);
171
172        // Mark this node as originally an async function
173        (generatorFunc.emitNode || (generatorFunc.emitNode = {} as EmitNode)).flags |= EmitFlags.AsyncFunctionBody | EmitFlags.ReuseTempVariableScope;
174
175        return factory.createCallExpression(
176            getUnscopedHelperName("__asyncGenerator"),
177            /*typeArguments*/ undefined,
178            [
179                hasLexicalThis ? factory.createThis() : factory.createVoidZero(),
180                factory.createIdentifier("arguments"),
181                generatorFunc
182            ]
183        );
184    }
185
186    function createAsyncDelegatorHelper(expression: Expression) {
187        context.requestEmitHelper(awaitHelper);
188        context.requestEmitHelper(asyncDelegator);
189        return factory.createCallExpression(
190            getUnscopedHelperName("__asyncDelegator"),
191            /*typeArguments*/ undefined,
192            [expression]
193        );
194    }
195
196    function createAsyncValuesHelper(expression: Expression) {
197        context.requestEmitHelper(asyncValues);
198        return factory.createCallExpression(
199            getUnscopedHelperName("__asyncValues"),
200            /*typeArguments*/ undefined,
201            [expression]
202        );
203    }
204
205    // ES2018 Destructuring Helpers
206
207    /** Given value: o, propName: p, pattern: { a, b, ...p } from the original statement
208     * `{ a, b, ...p } = o`, create `p = __rest(o, ["a", "b"]);`
209     */
210    function createRestHelper(value: Expression, elements: readonly BindingOrAssignmentElement[], computedTempVariables: readonly Expression[] | undefined, location: TextRange): Expression {
211        context.requestEmitHelper(restHelper);
212        const propertyNames: Expression[] = [];
213        let computedTempVariableOffset = 0;
214        for (let i = 0; i < elements.length - 1; i++) {
215            const propertyName = getPropertyNameOfBindingOrAssignmentElement(elements[i]);
216            if (propertyName) {
217                if (isComputedPropertyName(propertyName)) {
218                    Debug.assertIsDefined(computedTempVariables, "Encountered computed property name but 'computedTempVariables' argument was not provided.");
219                    const temp = computedTempVariables[computedTempVariableOffset];
220                    computedTempVariableOffset++;
221                    // typeof _tmp === "symbol" ? _tmp : _tmp + ""
222                    propertyNames.push(
223                        factory.createConditionalExpression(
224                            factory.createTypeCheck(temp, "symbol"),
225                            /*questionToken*/ undefined,
226                            temp,
227                            /*colonToken*/ undefined,
228                            factory.createAdd(temp, factory.createStringLiteral(""))
229                        )
230                    );
231                }
232                else {
233                    propertyNames.push(factory.createStringLiteralFromNode(propertyName));
234                }
235            }
236        }
237        return factory.createCallExpression(
238            getUnscopedHelperName("__rest"),
239            /*typeArguments*/ undefined,
240            [
241                value,
242                setTextRange(
243                    factory.createArrayLiteralExpression(propertyNames),
244                    location
245                )]
246        );
247    }
248
249    // ES2017 Helpers
250
251    function createAwaiterHelper(hasLexicalThis: boolean, hasLexicalArguments: boolean, promiseConstructor: EntityName | Expression | undefined, body: Block) {
252        context.requestEmitHelper(awaiterHelper);
253
254        const generatorFunc = factory.createFunctionExpression(
255            /*modifiers*/ undefined,
256            factory.createToken(SyntaxKind.AsteriskToken),
257            /*name*/ undefined,
258            /*typeParameters*/ undefined,
259            /*parameters*/ [],
260            /*type*/ undefined,
261            body
262        );
263
264        // Mark this node as originally an async function
265        (generatorFunc.emitNode || (generatorFunc.emitNode = {} as EmitNode)).flags |= EmitFlags.AsyncFunctionBody | EmitFlags.ReuseTempVariableScope;
266
267        return factory.createCallExpression(
268            getUnscopedHelperName("__awaiter"),
269            /*typeArguments*/ undefined,
270            [
271                hasLexicalThis ? factory.createThis() : factory.createVoidZero(),
272                hasLexicalArguments ? factory.createIdentifier("arguments") : factory.createVoidZero(),
273                promiseConstructor ? createExpressionFromEntityName(factory, promiseConstructor) : factory.createVoidZero(),
274                generatorFunc
275            ]
276        );
277    }
278
279    // ES2015 Helpers
280
281    function createExtendsHelper(name: Identifier) {
282        context.requestEmitHelper(extendsHelper);
283        return factory.createCallExpression(
284            getUnscopedHelperName("__extends"),
285            /*typeArguments*/ undefined,
286            [name, factory.createUniqueName("_super", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel)]
287        );
288    }
289
290    function createTemplateObjectHelper(cooked: ArrayLiteralExpression, raw: ArrayLiteralExpression) {
291        context.requestEmitHelper(templateObjectHelper);
292        return factory.createCallExpression(
293            getUnscopedHelperName("__makeTemplateObject"),
294            /*typeArguments*/ undefined,
295            [cooked, raw]
296        );
297    }
298
299    function createSpreadArrayHelper(to: Expression, from: Expression, packFrom: boolean) {
300        context.requestEmitHelper(spreadArrayHelper);
301        return factory.createCallExpression(
302            getUnscopedHelperName("__spreadArray"),
303            /*typeArguments*/ undefined,
304            [to, from, packFrom ? immutableTrue() : immutableFalse()]
305        );
306    }
307
308    // ES2015 Destructuring Helpers
309
310    function createValuesHelper(expression: Expression) {
311        context.requestEmitHelper(valuesHelper);
312        return factory.createCallExpression(
313            getUnscopedHelperName("__values"),
314            /*typeArguments*/ undefined,
315            [expression]
316        );
317    }
318
319    function createReadHelper(iteratorRecord: Expression, count: number | undefined) {
320        context.requestEmitHelper(readHelper);
321        return factory.createCallExpression(
322            getUnscopedHelperName("__read"),
323            /*typeArguments*/ undefined,
324            count !== undefined
325                ? [iteratorRecord, factory.createNumericLiteral(count + "")]
326                : [iteratorRecord]
327        );
328    }
329
330    // ES2015 Generator Helpers
331
332    function createGeneratorHelper(body: FunctionExpression) {
333        context.requestEmitHelper(generatorHelper);
334        return factory.createCallExpression(
335            getUnscopedHelperName("__generator"),
336            /*typeArguments*/ undefined,
337            [factory.createThis(), body]);
338    }
339
340    // ES Module Helpers
341
342    function createCreateBindingHelper(module: Expression, inputName: Expression, outputName: Expression | undefined) {
343        context.requestEmitHelper(createBindingHelper);
344        return factory.createCallExpression(
345            getUnscopedHelperName("__createBinding"),
346            /*typeArguments*/ undefined,
347            [factory.createIdentifier("exports"), module, inputName, ...(outputName ? [outputName] : [])]);
348    }
349
350    function createImportStarHelper(expression: Expression) {
351        context.requestEmitHelper(importStarHelper);
352        return factory.createCallExpression(
353            getUnscopedHelperName("__importStar"),
354            /*typeArguments*/ undefined,
355            [expression]
356        );
357    }
358
359    function createImportStarCallbackHelper() {
360        context.requestEmitHelper(importStarHelper);
361        return getUnscopedHelperName("__importStar");
362    }
363
364    function createImportDefaultHelper(expression: Expression) {
365        context.requestEmitHelper(importDefaultHelper);
366        return factory.createCallExpression(
367            getUnscopedHelperName("__importDefault"),
368            /*typeArguments*/ undefined,
369            [expression]
370        );
371    }
372
373    function createExportStarHelper(moduleExpression: Expression, exportsExpression: Expression = factory.createIdentifier("exports")) {
374        context.requestEmitHelper(exportStarHelper);
375        context.requestEmitHelper(createBindingHelper);
376        return factory.createCallExpression(
377            getUnscopedHelperName("__exportStar"),
378            /*typeArguments*/ undefined,
379            [moduleExpression, exportsExpression]
380        );
381    }
382
383    // Class Fields Helpers
384
385    function createClassPrivateFieldGetHelper(receiver: Expression, state: Identifier, kind: PrivateIdentifierKind, f: Identifier | undefined) {
386        context.requestEmitHelper(classPrivateFieldGetHelper);
387        let args;
388        if (!f) {
389            args = [receiver, state, factory.createStringLiteral(kind)];
390        }
391        else {
392            args = [receiver, state, factory.createStringLiteral(kind), f];
393        }
394        return factory.createCallExpression(getUnscopedHelperName("__classPrivateFieldGet"), /*typeArguments*/ undefined, args);
395    }
396
397    function createClassPrivateFieldSetHelper(receiver: Expression, state: Identifier, value: Expression, kind: PrivateIdentifierKind, f: Identifier | undefined) {
398        context.requestEmitHelper(classPrivateFieldSetHelper);
399        let args;
400        if (!f) {
401            args = [receiver, state, value, factory.createStringLiteral(kind)];
402        }
403        else {
404            args = [receiver, state, value, factory.createStringLiteral(kind), f];
405        }
406        return factory.createCallExpression(getUnscopedHelperName("__classPrivateFieldSet"), /*typeArguments*/ undefined, args);
407    }
408
409    function createClassPrivateFieldInHelper(state: Identifier, receiver: Expression) {
410        context.requestEmitHelper(classPrivateFieldInHelper);
411        return factory.createCallExpression(getUnscopedHelperName("__classPrivateFieldIn"), /* typeArguments*/ undefined, [state, receiver]);
412    }
413}
414
415/** @internal */
416export function compareEmitHelpers(x: EmitHelper, y: EmitHelper) {
417    if (x === y) return Comparison.EqualTo;
418    if (x.priority === y.priority) return Comparison.EqualTo;
419    if (x.priority === undefined) return Comparison.GreaterThan;
420    if (y.priority === undefined) return Comparison.LessThan;
421    return compareValues(x.priority, y.priority);
422}
423
424/**
425 * @param input Template string input strings
426 * @param args Names which need to be made file-level unique
427 *
428 * @internal
429 */
430export function helperString(input: TemplateStringsArray, ...args: string[]) {
431    return (uniqueName: EmitHelperUniqueNameCallback) => {
432        let result = "";
433        for (let i = 0; i < args.length; i++) {
434            result += input[i];
435            result += uniqueName(args[i]);
436        }
437        result += input[input.length - 1];
438        return result;
439    };
440}
441
442// TypeScript Helpers
443
444/** @internal */
445export const decorateHelper: UnscopedEmitHelper = {
446    name: "typescript:decorate",
447    importName: "__decorate",
448    scoped: false,
449    priority: 2,
450    text: `
451            var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
452                var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
453                if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
454                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;
455                return c > 3 && r && Object.defineProperty(target, key, r), r;
456            };`
457};
458
459/** @internal */
460export const metadataHelper: UnscopedEmitHelper = {
461    name: "typescript:metadata",
462    importName: "__metadata",
463    scoped: false,
464    priority: 3,
465    text: `
466            var __metadata = (this && this.__metadata) || function (k, v) {
467                if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
468            };`
469};
470
471/** @internal */
472export const paramHelper: UnscopedEmitHelper = {
473    name: "typescript:param",
474    importName: "__param",
475    scoped: false,
476    priority: 4,
477    text: `
478            var __param = (this && this.__param) || function (paramIndex, decorator) {
479                return function (target, key) { decorator(target, key, paramIndex); }
480            };`
481};
482
483// ES2018 Helpers
484
485/** @internal */
486export const assignHelper: UnscopedEmitHelper = {
487    name: "typescript:assign",
488    importName: "__assign",
489    scoped: false,
490    priority: 1,
491    text: `
492            var __assign = (this && this.__assign) || function () {
493                __assign = Object.assign || function(t) {
494                    for (var s, i = 1, n = arguments.length; i < n; i++) {
495                        s = arguments[i];
496                        for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
497                            t[p] = s[p];
498                    }
499                    return t;
500                };
501                return __assign.apply(this, arguments);
502            };`
503};
504
505/** @internal */
506export const awaitHelper: UnscopedEmitHelper = {
507    name: "typescript:await",
508    importName: "__await",
509    scoped: false,
510    text: `
511            var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }`
512};
513
514/** @internal */
515export const asyncGeneratorHelper: UnscopedEmitHelper = {
516    name: "typescript:asyncGenerator",
517    importName: "__asyncGenerator",
518    scoped: false,
519    dependencies: [awaitHelper],
520    text: `
521            var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
522                if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
523                var g = generator.apply(thisArg, _arguments || []), i, q = [];
524                return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
525                function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }
526                function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
527                function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
528                function fulfill(value) { resume("next", value); }
529                function reject(value) { resume("throw", value); }
530                function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
531            };`
532};
533
534/** @internal */
535export const asyncDelegator: UnscopedEmitHelper = {
536    name: "typescript:asyncDelegator",
537    importName: "__asyncDelegator",
538    scoped: false,
539    dependencies: [awaitHelper],
540    text: `
541            var __asyncDelegator = (this && this.__asyncDelegator) || function (o) {
542                var i, p;
543                return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i;
544                function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; } : f; }
545            };`
546};
547
548/** @internal */
549export const asyncValues: UnscopedEmitHelper = {
550    name: "typescript:asyncValues",
551    importName: "__asyncValues",
552    scoped: false,
553    text: `
554            var __asyncValues = (this && this.__asyncValues) || function (o) {
555                if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
556                var m = o[Symbol.asyncIterator], i;
557                return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
558                function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
559                function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
560            };`
561};
562
563// ES2018 Destructuring Helpers
564
565/** @internal */
566export const restHelper: UnscopedEmitHelper = {
567    name: "typescript:rest",
568    importName: "__rest",
569    scoped: false,
570    text: `
571            var __rest = (this && this.__rest) || function (s, e) {
572                var t = {};
573                for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
574                    t[p] = s[p];
575                if (s != null && typeof Object.getOwnPropertySymbols === "function")
576                    for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
577                        if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
578                            t[p[i]] = s[p[i]];
579                    }
580                return t;
581            };`
582};
583
584// ES2017 Helpers
585
586/** @internal */
587export const awaiterHelper: UnscopedEmitHelper = {
588    name: "typescript:awaiter",
589    importName: "__awaiter",
590    scoped: false,
591    priority: 5,
592    text: `
593            var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
594                function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
595                return new (P || (P = Promise))(function (resolve, reject) {
596                    function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
597                    function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
598                    function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
599                    step((generator = generator.apply(thisArg, _arguments || [])).next());
600                });
601            };`
602};
603
604// ES2015 Helpers
605
606/** @internal */
607export const extendsHelper: UnscopedEmitHelper = {
608    name: "typescript:extends",
609    importName: "__extends",
610    scoped: false,
611    priority: 0,
612    text: `
613            var __extends = (this && this.__extends) || (function () {
614                var extendStatics = function (d, b) {
615                    extendStatics = Object.setPrototypeOf ||
616                        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
617                        function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
618                    return extendStatics(d, b);
619                };
620
621                return function (d, b) {
622                    if (typeof b !== "function" && b !== null)
623                        throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
624                    extendStatics(d, b);
625                    function __() { this.constructor = d; }
626                    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
627                };
628            })();`
629};
630
631/** @internal */
632export const templateObjectHelper: UnscopedEmitHelper = {
633    name: "typescript:makeTemplateObject",
634    importName: "__makeTemplateObject",
635    scoped: false,
636    priority: 0,
637    text: `
638            var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) {
639                if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
640                return cooked;
641            };`
642};
643
644/** @internal */
645export const readHelper: UnscopedEmitHelper = {
646    name: "typescript:read",
647    importName: "__read",
648    scoped: false,
649    text: `
650            var __read = (this && this.__read) || function (o, n) {
651                var m = typeof Symbol === "function" && o[Symbol.iterator];
652                if (!m) return o;
653                var i = m.call(o), r, ar = [], e;
654                try {
655                    while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
656                }
657                catch (error) { e = { error: error }; }
658                finally {
659                    try {
660                        if (r && !r.done && (m = i["return"])) m.call(i);
661                    }
662                    finally { if (e) throw e.error; }
663                }
664                return ar;
665            };`
666};
667
668/** @internal */
669export const spreadArrayHelper: UnscopedEmitHelper = {
670    name: "typescript:spreadArray",
671    importName: "__spreadArray",
672    scoped: false,
673    text: `
674            var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
675                if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
676                    if (ar || !(i in from)) {
677                        if (!ar) ar = Array.prototype.slice.call(from, 0, i);
678                        ar[i] = from[i];
679                    }
680                }
681                return to.concat(ar || Array.prototype.slice.call(from));
682            };`
683};
684
685// ES2015 Destructuring Helpers
686
687/** @internal */
688export const valuesHelper: UnscopedEmitHelper = {
689    name: "typescript:values",
690    importName: "__values",
691    scoped: false,
692    text: `
693            var __values = (this && this.__values) || function(o) {
694                var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
695                if (m) return m.call(o);
696                if (o && typeof o.length === "number") return {
697                    next: function () {
698                        if (o && i >= o.length) o = void 0;
699                        return { value: o && o[i++], done: !o };
700                    }
701                };
702                throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
703            };`
704};
705
706// ES2015 Generator Helpers
707
708// The __generator helper is used by down-level transformations to emulate the runtime
709// semantics of an ES2015 generator function. When called, this helper returns an
710// object that implements the Iterator protocol, in that it has `next`, `return`, and
711// `throw` methods that step through the generator when invoked.
712//
713// parameters:
714//  @param thisArg  The value to use as the `this` binding for the transformed generator body.
715//  @param body     A function that acts as the transformed generator body.
716//
717// variables:
718//  _       Persistent state for the generator that is shared between the helper and the
719//          generator body. The state object has the following members:
720//            sent() - A method that returns or throws the current completion value.
721//            label  - The next point at which to resume evaluation of the generator body.
722//            trys   - A stack of protected regions (try/catch/finally blocks).
723//            ops    - A stack of pending instructions when inside of a finally block.
724//  f       A value indicating whether the generator is executing.
725//  y       An iterator to delegate for a yield*.
726//  t       A temporary variable that holds one of the following values (note that these
727//          cases do not overlap):
728//          - The completion value when resuming from a `yield` or `yield*`.
729//          - The error value for a catch block.
730//          - The current protected region (array of try/catch/finally/end labels).
731//          - The verb (`next`, `throw`, or `return` method) to delegate to the expression
732//            of a `yield*`.
733//          - The result of evaluating the verb delegated to the expression of a `yield*`.
734//  g       A temporary variable that holds onto the generator object until the generator
735//          is started, allowing it to also act as the `suspendedStart` state.
736//
737// functions:
738//  verb(n)     Creates a bound callback to the `step` function for opcode `n`.
739//  step(op)    Evaluates opcodes in a generator body until execution is suspended or
740//              completed.
741//
742// The __generator helper understands a limited set of instructions:
743//  0: next(value?)     - Start or resume the generator with the specified value.
744//  1: throw(error)     - Resume the generator with an exception. If the generator is
745//                        suspended inside of one or more protected regions, evaluates
746//                        any intervening finally blocks between the current label and
747//                        the nearest catch block or function boundary. If uncaught, the
748//                        exception is thrown to the caller.
749//  2: return(value?)   - Resume the generator as if with a return. If the generator is
750//                        suspended inside of one or more protected regions, evaluates any
751//                        intervening finally blocks.
752//  3: break(label)     - Jump to the specified label. If the label is outside of the
753//                        current protected region, evaluates any intervening finally
754//                        blocks.
755//  4: yield(value?)    - Yield execution to the caller with an optional value. When
756//                        resumed, the generator will continue at the next label.
757//  5: yield*(value)    - Delegates evaluation to the supplied iterator. When
758//                        delegation completes, the generator will continue at the next
759//                        label.
760//  6: catch(error)     - Handles an exception thrown from within the generator body. If
761//                        the current label is inside of one or more protected regions,
762//                        evaluates any intervening finally blocks between the current
763//                        label and the nearest catch block or function boundary. If
764//                        uncaught, the exception is thrown to the caller.
765//  7: endfinally       - Ends a finally block, resuming the last instruction prior to
766//                        entering a finally block.
767//
768// For examples of how these are used, see the comments in ./transformers/generators.ts
769/** @internal */
770export const generatorHelper: UnscopedEmitHelper = {
771    name: "typescript:generator",
772    importName: "__generator",
773    scoped: false,
774    priority: 6,
775    text: `
776            var __generator = (this && this.__generator) || function (thisArg, body) {
777                var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
778                return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
779                function verb(n) { return function (v) { return step([n, v]); }; }
780                function step(op) {
781                    if (f) throw new TypeError("Generator is already executing.");
782                    while (g && (g = 0, op[0] && (_ = 0)), _) try {
783                        if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
784                        if (y = 0, t) op = [op[0] & 2, t.value];
785                        switch (op[0]) {
786                            case 0: case 1: t = op; break;
787                            case 4: _.label++; return { value: op[1], done: false };
788                            case 5: _.label++; y = op[1]; op = [0]; continue;
789                            case 7: op = _.ops.pop(); _.trys.pop(); continue;
790                            default:
791                                if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
792                                if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
793                                if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
794                                if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
795                                if (t[2]) _.ops.pop();
796                                _.trys.pop(); continue;
797                        }
798                        op = body.call(thisArg, _);
799                    } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
800                    if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
801                }
802            };`
803};
804
805// ES Module Helpers
806
807/** @internal */
808export const createBindingHelper: UnscopedEmitHelper = {
809    name: "typescript:commonjscreatebinding",
810    importName: "__createBinding",
811    scoped: false,
812    priority: 1,
813    text: `
814            var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
815                if (k2 === undefined) k2 = k;
816                var desc = Object.getOwnPropertyDescriptor(m, k);
817                if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
818                  desc = { enumerable: true, get: function() { return m[k]; } };
819                }
820                Object.defineProperty(o, k2, desc);
821            }) : (function(o, m, k, k2) {
822                if (k2 === undefined) k2 = k;
823                o[k2] = m[k];
824            }));`
825};
826
827/** @internal */
828export const setModuleDefaultHelper: UnscopedEmitHelper = {
829    name: "typescript:commonjscreatevalue",
830    importName: "__setModuleDefault",
831    scoped: false,
832    priority: 1,
833    text: `
834            var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
835                Object.defineProperty(o, "default", { enumerable: true, value: v });
836            }) : function(o, v) {
837                o["default"] = v;
838            });`
839};
840
841// emit helper for `import * as Name from "foo"`
842/** @internal */
843export const importStarHelper: UnscopedEmitHelper = {
844    name: "typescript:commonjsimportstar",
845    importName: "__importStar",
846    scoped: false,
847    dependencies: [createBindingHelper, setModuleDefaultHelper],
848    priority: 2,
849    text: `
850            var __importStar = (this && this.__importStar) || function (mod) {
851                if (mod && mod.__esModule) return mod;
852                var result = {};
853                if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
854                __setModuleDefault(result, mod);
855                return result;
856            };`
857};
858
859// emit helper for `import Name from "foo"`
860/** @internal */
861export const importDefaultHelper: UnscopedEmitHelper = {
862    name: "typescript:commonjsimportdefault",
863    importName: "__importDefault",
864    scoped: false,
865    text: `
866            var __importDefault = (this && this.__importDefault) || function (mod) {
867                return (mod && mod.__esModule) ? mod : { "default": mod };
868            };`
869};
870
871/** @internal */
872export const exportStarHelper: UnscopedEmitHelper = {
873    name: "typescript:export-star",
874    importName: "__exportStar",
875    scoped: false,
876    dependencies: [createBindingHelper],
877    priority: 2,
878    text: `
879            var __exportStar = (this && this.__exportStar) || function(m, exports) {
880                for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
881            };`
882};
883
884/**
885 * Parameters:
886 *  @param receiver — The object from which the private member will be read.
887 *  @param state — One of the following:
888 *      - A WeakMap used to read a private instance field.
889 *      - A WeakSet used as an instance brand for private instance methods and accessors.
890 *      - A function value that should be the undecorated class constructor used to brand check private static fields, methods, and accessors.
891 *  @param kind — (optional pre TS 4.3, required for TS 4.3+) One of the following values:
892 *      - undefined — Indicates a private instance field (pre TS 4.3).
893 *      - "f" — Indicates a private field (instance or static).
894 *      - "m" — Indicates a private method (instance or static).
895 *      - "a" — Indicates a private accessor (instance or static).
896 *  @param f — (optional pre TS 4.3) Depends on the arguments for state and kind:
897 *      - If kind is "m", this should be the function corresponding to the static or instance method.
898 *      - If kind is "a", this should be the function corresponding to the getter method, or undefined if the getter was not defined.
899 *      - If kind is "f" and state is a function, this should be an object holding the value of a static field, or undefined if the static field declaration has not yet been evaluated.
900 * @internal
901 * Usage:
902 * This helper will only ever be used by the compiler in the following ways:
903 *
904 * Reading from a private instance field (pre TS 4.3):
905 *      __classPrivateFieldGet(<any>, <WeakMap>)
906 *
907 * Reading from a private instance field (TS 4.3+):
908 *      __classPrivateFieldGet(<any>, <WeakMap>, "f")
909 *
910 * Reading from a private instance get accessor (when defined, TS 4.3+):
911 *      __classPrivateFieldGet(<any>, <WeakSet>, "a", <function>)
912 *
913 * Reading from a private instance get accessor (when not defined, TS 4.3+):
914 *      __classPrivateFieldGet(<any>, <WeakSet>, "a", void 0)
915 *      NOTE: This always results in a runtime error.
916 *
917 * Reading from a private instance method (TS 4.3+):
918 *      __classPrivateFieldGet(<any>, <WeakSet>, "m", <function>)
919 *
920 * Reading from a private static field (TS 4.3+):
921 *      __classPrivateFieldGet(<any>, <constructor>, "f", <{ value: any }>)
922 *
923 * Reading from a private static get accessor (when defined, TS 4.3+):
924 *      __classPrivateFieldGet(<any>, <constructor>, "a", <function>)
925 *
926 * Reading from a private static get accessor (when not defined, TS 4.3+):
927 *      __classPrivateFieldGet(<any>, <constructor>, "a", void 0)
928 *      NOTE: This always results in a runtime error.
929 *
930 * Reading from a private static method (TS 4.3+):
931 *      __classPrivateFieldGet(<any>, <constructor>, "m", <function>)
932 */
933export const classPrivateFieldGetHelper: UnscopedEmitHelper = {
934    name: "typescript:classPrivateFieldGet",
935    importName: "__classPrivateFieldGet",
936    scoped: false,
937    text: `
938            var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
939                if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
940                if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
941                return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
942            };`
943};
944
945/**
946 * Parameters:
947 *  @param receiver — The object on which the private member will be set.
948 *  @param state — One of the following:
949 *      - A WeakMap used to store a private instance field.
950 *      - A WeakSet used as an instance brand for private instance methods and accessors.
951 *      - A function value that should be the undecorated class constructor used to brand check private static fields, methods, and accessors.
952 *  @param value — The value to set.
953 *  @param kind — (optional pre TS 4.3, required for TS 4.3+) One of the following values:
954 *       - undefined — Indicates a private instance field (pre TS 4.3).
955 *       - "f" — Indicates a private field (instance or static).
956 *       - "m" — Indicates a private method (instance or static).
957 *       - "a" — Indicates a private accessor (instance or static).
958 *   @param f — (optional pre TS 4.3) Depends on the arguments for state and kind:
959 *       - If kind is "m", this should be the function corresponding to the static or instance method.
960 *       - If kind is "a", this should be the function corresponding to the setter method, or undefined if the setter was not defined.
961 *       - If kind is "f" and state is a function, this should be an object holding the value of a static field, or undefined if the static field declaration has not yet been evaluated.
962 * @internal
963 * Usage:
964 * This helper will only ever be used by the compiler in the following ways:
965 *
966 * Writing to a private instance field (pre TS 4.3):
967 *      __classPrivateFieldSet(<any>, <WeakMap>, <any>)
968 *
969 * Writing to a private instance field (TS 4.3+):
970 *      __classPrivateFieldSet(<any>, <WeakMap>, <any>, "f")
971 *
972 * Writing to a private instance set accessor (when defined, TS 4.3+):
973 *      __classPrivateFieldSet(<any>, <WeakSet>, <any>, "a", <function>)
974 *
975 * Writing to a private instance set accessor (when not defined, TS 4.3+):
976 *      __classPrivateFieldSet(<any>, <WeakSet>, <any>, "a", void 0)
977 *      NOTE: This always results in a runtime error.
978 *
979 * Writing to a private instance method (TS 4.3+):
980 *      __classPrivateFieldSet(<any>, <WeakSet>, <any>, "m", <function>)
981 *      NOTE: This always results in a runtime error.
982 *
983 * Writing to a private static field (TS 4.3+):
984 *      __classPrivateFieldSet(<any>, <constructor>, <any>, "f", <{ value: any }>)
985 *
986 * Writing to a private static set accessor (when defined, TS 4.3+):
987 *      __classPrivateFieldSet(<any>, <constructor>, <any>, "a", <function>)
988 *
989 * Writing to a private static set accessor (when not defined, TS 4.3+):
990 *      __classPrivateFieldSet(<any>, <constructor>, <any>, "a", void 0)
991 *      NOTE: This always results in a runtime error.
992 *
993 * Writing to a private static method (TS 4.3+):
994 *      __classPrivateFieldSet(<any>, <constructor>, <any>, "m", <function>)
995 *      NOTE: This always results in a runtime error.
996 */
997export const classPrivateFieldSetHelper: UnscopedEmitHelper = {
998    name: "typescript:classPrivateFieldSet",
999    importName: "__classPrivateFieldSet",
1000    scoped: false,
1001    text: `
1002            var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
1003                if (kind === "m") throw new TypeError("Private method is not writable");
1004                if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
1005                if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
1006                return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
1007            };`
1008};
1009
1010/**
1011 * Parameters:
1012 *  @param state — One of the following:
1013 *      - A WeakMap when the member is a private instance field.
1014 *      - A WeakSet when the member is a private instance method or accessor.
1015 *      - A function value that should be the undecorated class constructor when the member is a private static field, method, or accessor.
1016 *  @param receiver — The object being checked if it has the private member.
1017 * @internal
1018 *
1019 * Usage:
1020 * This helper is used to transform `#field in expression` to
1021 *      `__classPrivateFieldIn(<weakMap/weakSet/constructor>, expression)`
1022 */
1023export const classPrivateFieldInHelper: UnscopedEmitHelper = {
1024    name: "typescript:classPrivateFieldIn",
1025    importName: "__classPrivateFieldIn",
1026    scoped: false,
1027    text: `
1028            var __classPrivateFieldIn = (this && this.__classPrivateFieldIn) || function(state, receiver) {
1029                if (receiver === null || (typeof receiver !== "object" && typeof receiver !== "function")) throw new TypeError("Cannot use 'in' operator on non-object");
1030                return typeof state === "function" ? receiver === state : state.has(receiver);
1031            };`
1032};
1033
1034let allUnscopedEmitHelpers: ReadonlyESMap<string, UnscopedEmitHelper> | undefined;
1035
1036/** @internal */
1037export function getAllUnscopedEmitHelpers() {
1038    return allUnscopedEmitHelpers || (allUnscopedEmitHelpers = arrayToMap([
1039        decorateHelper,
1040        metadataHelper,
1041        paramHelper,
1042        assignHelper,
1043        awaitHelper,
1044        asyncGeneratorHelper,
1045        asyncDelegator,
1046        asyncValues,
1047        restHelper,
1048        awaiterHelper,
1049        extendsHelper,
1050        templateObjectHelper,
1051        spreadArrayHelper,
1052        valuesHelper,
1053        readHelper,
1054        generatorHelper,
1055        importStarHelper,
1056        importDefaultHelper,
1057        exportStarHelper,
1058        classPrivateFieldGetHelper,
1059        classPrivateFieldSetHelper,
1060        classPrivateFieldInHelper,
1061        createBindingHelper,
1062        setModuleDefaultHelper
1063    ], helper => helper.name));
1064}
1065
1066/** @internal */
1067export const asyncSuperHelper: EmitHelper = {
1068    name: "typescript:async-super",
1069    scoped: true,
1070    text: helperString`
1071            const ${"_superIndex"} = name => super[name];`
1072};
1073
1074/** @internal */
1075export const advancedAsyncSuperHelper: EmitHelper = {
1076    name: "typescript:advanced-async-super",
1077    scoped: true,
1078    text: helperString`
1079            const ${"_superIndex"} = (function (geti, seti) {
1080                const cache = Object.create(null);
1081                return name => cache[name] || (cache[name] = { get value() { return geti(name); }, set value(v) { seti(name, v); } });
1082            })(name => super[name], (name, value) => super[name] = value);`
1083};
1084
1085/** @internal */
1086export function isCallToHelper(firstSegment: Expression, helperName: __String): boolean {
1087    return isCallExpression(firstSegment)
1088        && isIdentifier(firstSegment.expression)
1089        && (getEmitFlags(firstSegment.expression) & EmitFlags.HelperName) !== 0
1090        && firstSegment.expression.escapedText === helperName;
1091}
1092