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

rokucommunity / brs / #213

27 Jan 2025 05:30PM UTC coverage: 86.996% (-2.2%) from 89.205%
#213

push

web-flow
Implemented several improvements to SceneGraph (#87)

* Implemented several improvements to SceneGraph

* Fixed most test cases

* Reduced unnecessary code

* Fixed typo

* Added Warning when trying to create a non-existent Node

* Fixed parser

* Fixed unit tests

* Implemented support for `infoFields`

* Prettier fix

* Simplified execute callback code and matched behavior with Roku

* Adding comment to clarify the exception

2240 of 2807 branches covered (79.8%)

Branch coverage included in aggregate %.

139 of 304 new or added lines in 18 files covered. (45.72%)

2 existing lines in 1 file now uncovered.

6129 of 6813 relevant lines covered (89.96%)

27562.41 hits per line

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

6.85
/src/brsTypes/components/RoMessagePort.ts
1
import { BrsValue, ValueKind, BrsInvalid, BrsBoolean } from "../BrsType";
143✔
2
import { BrsComponent } from "./BrsComponent";
143✔
3
import { BrsEvent, BrsType, isBrsEvent } from "..";
143✔
4
import { Callable, StdlibArgument } from "../Callable";
143✔
5
import { Interpreter } from "../../interpreter";
6
import { Int32 } from "../Int32";
7

8
export class RoMessagePort extends BrsComponent implements BrsValue {
143✔
NEW
9
    readonly kind = ValueKind.Object;
×
10
    private readonly messageQueue: BrsEvent[];
11
    private readonly callbackQueue: Function[];
12
    private readonly callbackMap: Map<string, Function>;
13

14
    constructor() {
NEW
15
        super("roMessagePort");
×
NEW
16
        this.registerMethods({
×
17
            ifMessagePort: [this.waitMessage, this.getMessage, this.peekMessage],
18
        });
NEW
19
        this.messageQueue = [];
×
NEW
20
        this.callbackQueue = [];
×
NEW
21
        this.callbackMap = new Map();
×
22
    }
23

24
    pushMessage(object: BrsEvent) {
NEW
25
        this.messageQueue.push(object);
×
26
    }
27

28
    pushCallback(callback: Function) {
NEW
29
        this.callbackQueue.push(callback);
×
30
    }
31

32
    registerCallback(component: string, callback: Function) {
NEW
33
        this.callbackMap.set(component, callback);
×
34
    }
35

36
    unregisterCallback(component: string) {
NEW
37
        this.callbackMap.delete(component);
×
38
    }
39

40
    asyncCancel() {
NEW
41
        this.callbackQueue.length = 0;
×
42
    }
43

44
    toString(parent?: BrsType): string {
NEW
45
        return "<Component: roMessagePort>";
×
46
    }
47

48
    equalTo(other: BrsType) {
NEW
49
        return BrsBoolean.False;
×
50
    }
51

52
    wait(_: Interpreter, ms: number) {
NEW
53
        const loop = ms === 0;
×
NEW
54
        ms += performance.now();
×
55

NEW
56
        while (loop || performance.now() < ms) {
×
NEW
57
            this.updateMessageQueue();
×
NEW
58
            const msg = this.getNextMessage();
×
NEW
59
            if (msg !== BrsInvalid.Instance) {
×
NEW
60
                return msg;
×
61
            }
62
        }
NEW
63
        return BrsInvalid.Instance;
×
64
    }
65

66
    private updateMessageQueue() {
67
        // TODO: Yield to get messages
NEW
68
        if (this.callbackMap.size > 0) {
×
NEW
69
            for (const [_, callback] of this.callbackMap.entries()) {
×
NEW
70
                const events = callback();
×
NEW
71
                this.messageQueue.push(...events.filter(isBrsEvent));
×
72
            }
73
        }
74
    }
75

76
    private getNextMessage(): BrsEvent | BrsInvalid {
NEW
77
        if (this.messageQueue.length > 0) {
×
NEW
78
            return this.messageQueue.shift() ?? BrsInvalid.Instance;
×
NEW
79
        } else if (this.callbackQueue.length > 0) {
×
NEW
80
            let callback = this.callbackQueue.shift();
×
NEW
81
            if (typeof callback === "function") {
×
NEW
82
                const event = callback();
×
NEW
83
                if (event !== BrsInvalid.Instance) {
×
NEW
84
                    return event;
×
85
                }
86
            }
87
        }
NEW
88
        return BrsInvalid.Instance;
×
89
    }
90

91
    // ifMessagePort ------------------------------------------------------------------------------------
92

93
    /** Waits until an event object is available or timeout milliseconds have passed. */
NEW
94
    private readonly waitMessage = new Callable("waitMessage", {
×
95
        signature: {
96
            args: [new StdlibArgument("timeout", ValueKind.Int32)],
97
            returns: ValueKind.Object,
98
        },
99
        impl: (interpreter: Interpreter, timeout: Int32) => {
NEW
100
            return this.wait(interpreter, timeout.getValue());
×
101
        },
102
    });
103

104
    /** If an event object is available, it is returned. Otherwise invalid is returned. */
NEW
105
    private readonly getMessage = new Callable("getMessage", {
×
106
        signature: {
107
            args: [],
108
            returns: ValueKind.Dynamic,
109
        },
110
        impl: (_: Interpreter) => {
NEW
111
            this.updateMessageQueue();
×
NEW
112
            return this.getNextMessage();
×
113
        },
114
    });
115

116
    /** Similar to GetMessage() but the returned object (if not invalid) remains in the message queue. */
NEW
117
    private readonly peekMessage = new Callable("peekMessage", {
×
118
        signature: {
119
            args: [],
120
            returns: ValueKind.Dynamic,
121
        },
122
        impl: (_: Interpreter) => {
NEW
123
            this.updateMessageQueue();
×
NEW
124
            if (this.messageQueue.length > 0) {
×
NEW
125
                return this.messageQueue[0];
×
126
            }
NEW
127
            if (this.callbackQueue.length > 0) {
×
NEW
128
                let callback = this.callbackQueue[0];
×
NEW
129
                if (callback) {
×
NEW
130
                    const msg = callback();
×
NEW
131
                    if (msg !== BrsInvalid.Instance) {
×
NEW
132
                        this.messageQueue.push(msg);
×
NEW
133
                        return msg;
×
134
                    }
135
                }
136
            }
NEW
137
            return BrsInvalid.Instance;
×
138
        },
139
    });
140
}
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

© 2025 Coveralls, Inc