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