Skip to content
File

Blob: types/test/transforms/globals.spec.ts

typescript104 lines
1// Copyright (c) 2022-2023 Cloudflare, Inc.
2// Licensed under the Apache 2.0 license found in the LICENSE file or at:
3// https://opensource.org/licenses/Apache-2.0
4 
5import assert from "assert";
6import { test } from "node:test";
7import path from "path";
8import ts from "typescript";
9import { printer } from "../../src/print";
10import { createMemoryProgram } from "../../src/program";
11import { createGlobalScopeTransformer } from "../../src/transforms";
12 
13test("createGlobalScopeTransformer: extracts global scope", () => {
14 const source = `type WorkerGlobalScopeEventMap = {
15 fetch: Event;
16 scheduled: Event;
17};
18declare class EventTarget<EventMap extends Record<string, Event> = Record<string, Event>> {
19 constructor();
20 addEventListener<Type extends keyof EventMap>(type: Type, handler: (event: EventMap[Type]) => void): void; // MethodDeclaration
21 removeEventListener<Type extends keyof EventMap>(type: Type, handler: (event: EventMap[Type]) => void): void; // MethodDeclaration
22 dispatchEvent(event: EventMap[keyof EventMap]): void; // MethodDeclaration
23}
24declare class WorkerGlobalScope extends EventTarget<WorkerGlobalScopeEventMap> {
25 thing: string; // PropertyDeclaration
26 static readonly CONSTANT: 42; // PropertyDeclaration
27 get property(): number; // GetAccessorDeclaration
28 set property(value: number); // GetAccessorDeclaration
29}
30declare class DOMException {
31}
32declare abstract class Crypto {
33}
34declare abstract class Console {
35}
36interface ServiceWorkerGlobalScope extends WorkerGlobalScope {
37 DOMException: typeof DOMException; // PropertySignature
38 btoa(value: string): string; // MethodSignature
39 crypto: Crypto; // PropertySignature
40 get console(): Console; // GetAccessorDeclaration
41}
42`;
43 
44 const sourcePath = path.resolve(__dirname, "source.ts");
45 const sources = new Map([[sourcePath, source]]);
46 const program = createMemoryProgram(sources);
47 const checker = program.getTypeChecker();
48 const sourceFile = program.getSourceFile(sourcePath);
49 assert(sourceFile !== undefined);
50 
51 const result = ts.transform(sourceFile, [
52 createGlobalScopeTransformer(checker),
53 ]);
54 assert.strictEqual(result.transformed.length, 1);
55 
56 const output = printer.printFile(result.transformed[0]);
57 assert.strictEqual(
58 output,
59 // Extracted global nodes inserted after ServiceWorkerGlobalScope
60 source +
61 `declare function addEventListener<Type extends keyof WorkerGlobalScopeEventMap>(type: Type, handler: (event: WorkerGlobalScopeEventMap[Type]) => void): void;
62declare function removeEventListener<Type extends keyof WorkerGlobalScopeEventMap>(type: Type, handler: (event: WorkerGlobalScopeEventMap[Type]) => void): void;
63declare function dispatchEvent(event: WorkerGlobalScopeEventMap[keyof WorkerGlobalScopeEventMap]): void;
64declare const thing: string;
65declare const CONSTANT: 42;
66declare const property: number;
67declare function btoa(value: string): string;
68declare const crypto: Crypto;
69declare const console: Console;
70`
71 );
72});
73 
74test("createGlobalScopeTransformer: inlining type parameters in heritage", () => {
75 const source = `declare class A<T> {
76 thing: T;
77}
78declare class B<T> extends A<T> {
79}
80declare class ServiceWorkerGlobalScope extends B<string> {
81}
82`;
83 
84 const sourcePath = path.resolve(__dirname, "source.ts");
85 const sources = new Map([[sourcePath, source]]);
86 const program = createMemoryProgram(sources);
87 const checker = program.getTypeChecker();
88 const sourceFile = program.getSourceFile(sourcePath);
89 assert(sourceFile !== undefined);
90 
91 const result = ts.transform(sourceFile, [
92 createGlobalScopeTransformer(checker),
93 ]);
94 assert.strictEqual(result.transformed.length, 1);
95 
96 const output = printer.printFile(result.transformed[0]);
97 assert.strictEqual(
98 output,
99 source +
100 `declare const thing: string;
101`
102 );
103});