• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1describe("unittests:: evaluation:: externalModules", () => {
2    // https://github.com/microsoft/TypeScript/issues/35420
3    it("Correct 'this' in function exported from external module", async () => {
4        const result = evaluator.evaluateTypeScript({
5            files: {
6                "/.src/output.ts": `
7                    export const output: any[] = [];
8                `,
9                "/.src/other.ts": `
10                    import { output } from "./output";
11                    export function f(this: any, expected) {
12                        output.push(this === expected);
13                    }
14
15                    // 0
16                    f(undefined);
17                `,
18                "/.src/main.ts": `
19                    export { output } from "./output";
20                    import { output } from "./output";
21                    import { f } from "./other";
22                    import * as other from "./other";
23
24                    // 1
25                    f(undefined);
26
27                    // 2
28                    const obj = {};
29                    f.call(obj, obj);
30
31                    // 3
32                    other.f(other);
33                `
34            },
35            rootFiles: ["/.src/main.ts"],
36            main: "/.src/main.ts"
37        });
38        assert.equal(result.output[0], true); // `f(undefined)` inside module. Existing behavior is correct.
39        assert.equal(result.output[1], true); // `f(undefined)` from import. New behavior to match first case.
40        assert.equal(result.output[2], true); // `f.call(obj, obj)`. Behavior of `.call` (or `.apply`, etc.) should not be affected.
41        assert.equal(result.output[3], true); // `other.f(other)`. `this` is still namespace because it is left of `.`.
42    });
43
44    it("Correct 'this' in function expression exported from external module", async () => {
45        const result = evaluator.evaluateTypeScript({
46            files: {
47                "/.src/output.ts": `
48                    export const output: any[] = [];
49                `,
50                "/.src/other.ts": `
51                    import { output } from "./output";
52                    export const f = function(this: any, expected) {
53                        output.push(this === expected);
54                    }
55
56                    // 0
57                    f(undefined);
58                `,
59                "/.src/main.ts": `
60                    export { output } from "./output";
61                    import { output } from "./output";
62                    import { f } from "./other";
63                    import * as other from "./other";
64
65                    // 1
66                    f(undefined);
67
68                    // 2
69                    const obj = {};
70                    f.call(obj, obj);
71
72                    // 3
73                    other.f(other);
74                `
75            },
76            rootFiles: ["/.src/main.ts"],
77            main: "/.src/main.ts"
78        });
79        assert.equal(result.output[0], true); // `f(undefined)` inside module. Existing behavior is incorrect.
80        assert.equal(result.output[1], true); // `f(undefined)` from import. New behavior to match first case.
81        assert.equal(result.output[2], true); // `f.call(obj, obj)`. Behavior of `.call` (or `.apply`, etc.) should not be affected.
82        assert.equal(result.output[3], true); // `other.f(other)`. `this` is still namespace because it is left of `.`.
83    });
84});