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