• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

rokucommunity / roku-debug / 26120672946

19 May 2026 07:37PM UTC coverage: 70.727% (+0.7%) from 70.049%
26120672946

Pull #351

github

web-flow
Merge eb0b2e542 into 5bbd82240
Pull Request #351: 0.23.8

3328 of 5046 branches covered (65.95%)

Branch coverage included in aggregate %.

5834 of 7908 relevant lines covered (73.77%)

35.01 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

61.11
/src/bsc/BscProjectThreaded.ts
1
import { Deferred } from 'brighterscript';
2
import type { Position, ProgramBuilder, Range } from 'brighterscript';
2✔
3
import type { ExtractMethods, DisposableLike, MaybePromise } from '../interfaces';
2✔
4
import type { BscProject, ScopeFunction } from './BscProject';
2✔
5
import { bscProjectWorkerPool } from './threading/BscProjectWorkerPool';
2✔
6
import type { MethodNames, WorkerMessage } from './threading/ThreadMessageHandler';
2✔
7
import { ThreadMessageHandler } from './threading/ThreadMessageHandler';
2✔
8
import type { Worker } from 'worker_threads';
2✔
9
import { util } from '../util';
10
import { logger } from '../logging';
11

337✔
12

337✔
13
export class BscProjectThreaded implements ExtractMethods<BscProject> {
337✔
14

15
    public logger = logger.createLogger('[BscProjectThreaded]');
16

17
    private worker: Worker;
337✔
18

19
    private messageHandler: ThreadMessageHandler<BscProject>;
20

21
    private activateDeferred = new Deferred();
22
    private errorDeferred = new Deferred();
23

×
24
    /**
25
     * Has this project finished activating (either resolved or rejected...)
26
     */
27
    public get isActivated() {
28
        return this.activateDeferred.isCompleted;
29
    }
×
30

31
    /**
32
     * If an error occurs at any time during the worker's lifetime, it will be caught and stored here.
×
33
     */
34
    public isErrored() {
35
        return this.errorDeferred.isCompleted;
36
    }
37

38
    private ready() {
39
        return Promise.race([
40
            //if we've encountered an error, reject immediately. The underlying error should propagate up
1✔
41
            this.errorDeferred.promise,
42
            //wait for the activate to finish. This should typically be the only promise that resolves
1✔
43
            this.activateDeferred.promise
44
        ]);
1✔
45
    }
×
46

×
47
    public async activate(options: Parameters<ProgramBuilder['run']>[0]) {
48
        const timeEnd = this.logger.timeStart('log', 'activate');
×
49

50
        // start a new worker thread or get an unused existing thread
51
        this.worker = bscProjectWorkerPool.getWorker();
52

53
        //!!!IMPORTANT!!! this observer must be registered in order to prevent the worker thread from crashing the main thread
1✔
54
        this.worker.on('error', (error) => {
55
            this.logger.error('Worker encountered an error', error);
56
            this.errorDeferred.reject(error);
57
            //!!!IMPORTANT!!! this is required to prevent node from freaking out about an uncaught promise
58
            this.errorDeferred.promise.catch(e => {
59
                //do nothing. this is just to prevent node from freaking out about an uncaught promise
60
            });
1✔
61
        });
62

×
63
        //link the message handler to the worker
64
        this.messageHandler = new ThreadMessageHandler<BscProject>({
1✔
65
            name: 'MainThread',
1✔
66
            port: this.worker,
1✔
67
            onRequest: this.processRequest.bind(this),
68
            onUpdate: this.processUpdate.bind(this)
69
        });
×
70

71
        //set up some disposables to be cleaned up
1✔
72
        this.disposables.push(
1✔
73
            this.messageHandler,
74
            //when disposed, move the worker back to the pool so it can be used again
75
            () => bscProjectWorkerPool.releaseWorker(this.worker)
76
        );
77

78
        //send the request to the worker to activate itself
×
79
        try {
80
            await this.messageHandler.sendRequest('activate', { data: [options] });
81
            this.activateDeferred.resolve();
82
        } catch (e) {
83
            this.activateDeferred.reject(e);
84
        }
×
85
        timeEnd();
86

87
        return this.activateDeferred.promise;
88
    }
89

90
    /**
91
     * Get all of the functions available for all scopes for this file.
92
     */
93
    public async getScopeFunctionsForFile(options: { relativePath: string }): Promise<Array<ScopeFunction>> {
×
94
        return this.sendStandardRequest('getScopeFunctionsForFile', options);
×
95
    }
96

97
    /**
×
98
     * Get the range of the scope that contains the specified position
99
     */
100
    public getScopeRange(options: { relativePath: string; position: Position }): Promise<Range> {
101
        return this.sendStandardRequest('getScopeRange', options);
102
    }
103

104
    /**
105
     * Send a request with the standard structure
106
     * @param name the name of the request
107
     * @param data the array of data to send
108
     * @returns the response from the request
109
     */
110
    private async sendStandardRequest<T>(name: MethodNames<BscProject>, ...data: any[]) {
111
        await this.ready();
112
        const response = await this.messageHandler.sendRequest<T>(name, {
113
            data: data
114
        });
115
        return response.data;
×
116
    }
117

118
    /**
2✔
119
     * If the client sends a request, it will be processed here
120
     */
121
    private processRequest(request: WorkerMessage) {
122
        //the thread does not currently send any requests
123
    }
124

125
    /**
126
     * If the client sends an update, it will be processed here
127
     */
128
    private processUpdate(update: WorkerMessage) {
129
        //the thread does not currently send any requests
130
    }
131

132
    /**
133
     * List of disposables to clean up when this instance is disposed
134
     */
135
    public disposables: DisposableLike[] = [];
136

137
    /**
138
     * Clean up all resources used by this instance
139
     */
140
    public dispose() {
141
        util.applyDispose(this.disposables);
142
    }
143
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc