• 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

91.3
/src/PrintedObjectParser.ts
1
export class PrintedObjectParser {
2
    constructor(private line: string) {
2✔
3
        this.parse();
2✔
4
    }
5
    private currentIndex: number;
6

11✔
7
    private key: string;
11✔
8
    private value: string;
9

10
    public get result() {
11✔
11
        return this.key && this.value ? {
12
            key: this.key,
13
            value: this.value
14
        } : undefined;
15
    }
16

17
    private take() {
113✔
18
        //iterate from right-to-left, since the rhs strings have quotes around them (but the lhs ones do not)
19
        return this.line[this.currentIndex--];
20
    }
272✔
21

22
    private peek() {
23
        return this.line[this.currentIndex];
24
    }
25

26
    /**
94✔
27
     * Indicates whether the index is at or past the end of the line
28
     */
29
    private isAtEnd() {
30
        return this.currentIndex >= this.line.length;
31
    }
32

15✔
33
    /**
22✔
34
     * get a string with all of the characters up to
22✔
35
     * @param stopChar
94!
36
     */
×
37
    private takeUntil(stopChar: string, includeStopChar = true) {
38
        let result = '';
94✔
39
        while (this.peek() && this.peek() !== stopChar) {
40
            if (this.isAtEnd()) {
22✔
41
                return undefined;
15✔
42
            }
43
            result += this.take();
22✔
44
        }
45
        if (includeStopChar) {
46
            result += this.take();
47
        }
48
        return result;
49
    }
11✔
50

11✔
51
    /**
×
52
     * Take all whitespace chars until a non-whitespace char is found
53
     */
11✔
54
    private takeWhitespace() {
55
        let result = '';
56
        while (this.peek() === ' ' || this.peek() === '\t') {
44✔
57
            result += this.take();
58
        }
59
        return result;
60
    }
11✔
61

11✔
62
    private hasValue() {
63
        return !!this.value;
11✔
64
    }
65

11✔
66
    private parse() {
11✔
67
        //throw out the beginning 4 characters of the line that roku always includes for object properties
11✔
68
        this.line = this.line.substring(4);
69

11!
70
        this.currentIndex = this.line.length - 1;
71

11✔
72
        //trim right whitespace
11✔
73
        this.takeWhitespace();
74

75
        //try to get the value. All of these methods will immediately exit if value was already found
76
        this.tryTakeStringValue();
11!
77
        this.tryTakeComponentValue();
×
78
        this.tryTakeBasicValue();
79

80
        //if we found a value, then the remaining characters are the key
81
        if (this.hasValue()) {
11✔
82
            //we process backwards, so reverse the value
83
            this.value = this.value.split('').reverse().join('').trim();
84
            this.takeKey();
85
        }
2✔
86
    }
87

88
    private tryTakeStringValue() {
89
        if (this.hasValue()) {
11✔
90
            return;
2✔
91
        }
92

93
        //TODO support complex strings like `"cat says "bark" like a dog"`
9✔
94

95
        //if ends with quote
2✔
96
        if (this.peek() === '"') {
97
            //very primative take (does not support quotes embedded inside quotes).
98
            //roku does not escape the quotes inside of quotes for this type of print, unfortunately
99

100
            //take the opening quote, and all chars up to (and including) the closing quote
101
            this.value = this.take() + this.takeUntil('"');
102
        }
103
    }
11✔
104

4✔
105
    private tryTakeComponentValue() {
106
        if (this.hasValue()) {
7✔
107
            return;
108
        }
109
        //if ends with greaterThan, this is a component reference
110
        if (this.peek() === '>') {
111
            //take until lessThan
112
            this.value = this.take() + this.takeUntil('<');
113
        }
11✔
114
    }
11✔
115

116
    /**
117
     * Look for basic values like int, boolean, and other non-string and non-object values.
2✔
118
     * These are going to be non-semicolon characters found to the right of a semicolon (i.e. `age: 123` or `isAlive: true`)
119
     */
120
    private tryTakeBasicValue() {
121
        if (this.hasValue()) {
122
            return;
123
        }
124
        this.value = this.takeUntil(':', false);
125
    }
126

127
    /**
128
     * Clean up the remaining characters, and use them as the key
129
     */
130
    private takeKey() {
131
        //throw out characters until we reach a colon
132
        this.takeUntil(':');
133
        this.key = this.line.substring(0, this.currentIndex + 1);
134
    }
135
}
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