@effindomv2/fui-as 0.1.36 → 0.1.39

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/browser/routed-app-conventions.ts +1 -1
  2. package/browser/src/common-harness.ts +1 -27
  3. package/browser/src/index.ts +19 -26
  4. package/browser/src/routed-harness.ts +1 -194
  5. package/browser/src/shared-browser.ts +6 -0
  6. package/package.json +26 -16
  7. package/scripts/build.sh +51 -47
  8. package/scripts/framework-host-services.ts +1 -1
  9. package/scripts/generate-host-events.ts +15 -241
  10. package/scripts/generate-host-services.ts +13 -261
  11. package/scripts/hostgen/assemblyscript-host-events.ts +165 -0
  12. package/scripts/hostgen/assemblyscript-host-services.ts +207 -0
  13. package/scripts/hostgen/common.ts +73 -0
  14. package/scripts/hostgen/registry.ts +159 -0
  15. package/src/Fui.ts +70 -4
  16. package/src/FuiExports.ts +13 -1
  17. package/src/bindings/ui.ts +165 -8
  18. package/src/controls/Button.ts +98 -71
  19. package/src/controls/Checkbox.ts +23 -21
  20. package/src/controls/ComboBox.ts +1201 -0
  21. package/src/controls/ContextMenu.ts +279 -165
  22. package/src/controls/Dialog.ts +91 -17
  23. package/src/controls/Dropdown.ts +101 -333
  24. package/src/controls/NavLink.ts +29 -6
  25. package/src/controls/Popup.ts +10 -5
  26. package/src/controls/ProgressBar.ts +1 -2
  27. package/src/controls/RadioButton.ts +34 -13
  28. package/src/controls/RadioGroup.ts +32 -19
  29. package/src/controls/Slider.ts +21 -23
  30. package/src/controls/Switch.ts +34 -17
  31. package/src/controls/index.ts +2 -1
  32. package/src/controls/internal/ButtonPresenter.ts +5 -2
  33. package/src/controls/internal/CheckboxIndicatorPresenter.ts +10 -10
  34. package/src/controls/internal/DropdownChevronPresenter.ts +3 -3
  35. package/src/controls/internal/DropdownFieldPresenter.ts +6 -6
  36. package/src/controls/internal/DropdownOptionRowPresenter.ts +5 -4
  37. package/src/controls/internal/PressableLabeledControl.ts +4 -7
  38. package/src/controls/internal/RadioIndicatorPresenter.ts +7 -7
  39. package/src/controls/internal/SelectablePopupList.ts +463 -0
  40. package/src/controls/internal/SliderPresenter.ts +5 -5
  41. package/src/controls/internal/SwitchIndicatorPresenter.ts +63 -17
  42. package/src/controls/internal/TextInputCore.ts +307 -41
  43. package/src/controls/internal/TextInputPresenter.ts +2 -2
  44. package/src/controls/templating.ts +10 -0
  45. package/src/core/Application.ts +19 -9
  46. package/src/core/Bitmap.ts +219 -1
  47. package/src/core/ContextMenuManager.ts +128 -44
  48. package/src/core/DebugApi.ts +17 -2
  49. package/src/core/DragGesture.ts +8 -7
  50. package/src/core/EventRouter.ts +332 -12
  51. package/src/core/Fetch.ts +15 -7
  52. package/src/core/FetchFfi.ts +1 -15
  53. package/src/core/File.ts +75 -34
  54. package/src/core/FocusAdornerManager.ts +3 -3
  55. package/src/core/FocusVisibility.ts +7 -0
  56. package/src/core/FrameScheduler.ts +126 -0
  57. package/src/core/ImageSampling.ts +43 -0
  58. package/src/core/Logger.ts +2 -0
  59. package/src/core/MobileTextSelectionToolbarManager.ts +901 -0
  60. package/src/core/Node.ts +1039 -97
  61. package/src/core/Platform.ts +16 -16
  62. package/src/core/SelectionHandleAdornerManager.ts +697 -0
  63. package/src/core/Theme.ts +34 -20
  64. package/src/core/ToolTipManager.ts +3 -3
  65. package/src/core/Typography.ts +411 -19
  66. package/src/core/Worker.ts +69 -33
  67. package/src/core/event_exports.ts +123 -5
  68. package/src/core/ffi.ts +5 -746
  69. package/src/core/generated/FetchHostAbi.ts +10 -0
  70. package/src/core/generated/FrameworkHostServices.ts +1 -1
  71. package/src/core/generated/HostAbi.ts +220 -0
  72. package/src/core/generated/UiAbi.ts +356 -0
  73. package/src/core/generated/UiEnums.ts +186 -0
  74. package/src/drawing/DrawCallback.ts +34 -0
  75. package/src/drawing/DrawContext.ts +189 -0
  76. package/src/drawing/Paint.ts +34 -0
  77. package/src/drawing/Path.ts +40 -0
  78. package/src/nodes/CustomDrawable.ts +61 -0
  79. package/src/nodes/FlexBox.ts +57 -11
  80. package/src/nodes/Grid.ts +5 -5
  81. package/src/nodes/Image.ts +20 -1
  82. package/src/nodes/RichText.ts +36 -25
  83. package/src/nodes/ScrollBar.ts +2 -1
  84. package/src/nodes/ScrollBox.ts +7 -2
  85. package/src/nodes/ScrollView.ts +17 -6
  86. package/src/nodes/Svg.ts +18 -1
  87. package/src/nodes/Text.ts +1 -1
  88. package/src/nodes/TextCore.ts +115 -20
  89. package/src/nodes/index.ts +3 -1
  90. package/src/text/DynamicTextLayout.ts +275 -0
  91. package/src/text/TextLayout.ts +308 -0
  92. package/src/worker/Worker.ts +3 -36
  93. package/src/worker/WorkerJob.ts +5 -9
  94. package/src/worker/ffi.ts +0 -6
  95. package/browser/src/common-harness/host-imports.ts +0 -447
  96. package/browser/src/common-harness/interop.ts +0 -39
  97. package/browser/src/common-harness/managed-harness-bitmap-host.ts +0 -92
  98. package/browser/src/common-harness/managed-harness-fetch-host.ts +0 -201
  99. package/browser/src/common-harness/managed-harness-file-host.ts +0 -1066
  100. package/browser/src/common-harness/managed-harness-file-payloads.ts +0 -143
  101. package/browser/src/common-harness/managed-harness-file-types.ts +0 -71
  102. package/browser/src/common-harness/managed-harness-session.ts +0 -15
  103. package/browser/src/common-harness/managed-harness.ts +0 -1451
  104. package/browser/src/common-harness/managed-history.ts +0 -168
  105. package/browser/src/common-harness/persisted-restore-policy.ts +0 -50
  106. package/browser/src/common-harness/persisted-ui-state-controller.ts +0 -309
  107. package/browser/src/common-harness/text-session-bridge.ts +0 -452
  108. package/browser/src/common-harness/types.ts +0 -205
  109. package/browser/src/common-harness/ui-chrome.ts +0 -206
  110. package/browser/src/common-harness/ui-imports.ts +0 -553
  111. package/browser/src/common-harness/wasm-module-cache.ts +0 -47
  112. package/browser/src/file-processing-worker.ts +0 -89
  113. package/browser/src/host-events.ts +0 -118
  114. package/browser/src/host-services.ts +0 -483
  115. package/browser/src/persisted-ui-state.ts +0 -206
  116. package/browser/src/routed-app-conventions.ts +0 -292
  117. package/browser/src/worker-bootstrap.ts +0 -916
  118. package/browser/src/worker-manager.ts +0 -234
  119. package/browser/src/worker-types.ts +0 -68
@@ -0,0 +1,275 @@
1
+ import * as ui from "../bindings/ui";
2
+ import { TextOverflow } from "../core/ffi";
3
+ import { FontFamily, FontStack, FontStyle, FontWeight } from "../core/Typography";
4
+ import { TextAlign, TextVerticalAlign, Unit } from "../core/ffi";
5
+ import { TextLayout, TextLayoutReadyEventArgs, TextLayoutReadyHandler } from "./TextLayout";
6
+
7
+ export enum DynamicTextOverflow {
8
+ Reject = 0,
9
+ FallbackShape = 1,
10
+ }
11
+
12
+ export type DynamicTextLayoutReadyHandler<Owner> = TextLayoutReadyHandler<Owner>;
13
+
14
+ /**
15
+ * Short, single-style text resource for labels that change frequently.
16
+ *
17
+ * Stage 4 keeps the public API and validation contract separate from the
18
+ * retained text node backing used by `TextLayout`. A later core resource pass
19
+ * can replace the backing without changing call sites.
20
+ */
21
+ export class DynamicTextLayout extends TextLayout {
22
+ private charsetValue: string = "";
23
+ private overflowValue: DynamicTextOverflow = DynamicTextOverflow.FallbackShape;
24
+ private currentTextValue: string = "";
25
+ private numericMode: bool = false;
26
+ private numericPrecisionValue: i32 = -1;
27
+ private numericPrefixValue: string = "";
28
+ private numericSuffixValue: string = "";
29
+ private hasNumericValue: bool = false;
30
+ private numericValue: f64 = 0.0;
31
+
32
+ constructor(charset: string = "") {
33
+ super("");
34
+ this.charsetValue = charset;
35
+ }
36
+
37
+ static fixedCharset(charset: string): DynamicTextLayout {
38
+ return new DynamicTextLayout(charset);
39
+ }
40
+
41
+ static numeric(): DynamicTextLayout {
42
+ const layout = new DynamicTextLayout("0123456789.-");
43
+ layout.numericMode = true;
44
+ return layout;
45
+ }
46
+
47
+ get currentText(): string {
48
+ return this.currentTextValue;
49
+ }
50
+
51
+ /** @internal */
52
+ _prepareNow(): void {
53
+ ui.setDynamicTextCharset(this._drawNode().builtHandle, this.charsetValue);
54
+ super._prepareNow();
55
+ }
56
+
57
+ setText(value: string): bool {
58
+ if (!this.supportsText(value)) {
59
+ if (this.overflowValue == DynamicTextOverflow.Reject) {
60
+ return false;
61
+ }
62
+ }
63
+ const wasReady = this.isReady;
64
+ this.currentTextValue = value;
65
+ super.text(value);
66
+ if (wasReady) {
67
+ this._prepareNow();
68
+ }
69
+ return true;
70
+ }
71
+
72
+ overflow(mode: DynamicTextOverflow): this {
73
+ this.overflowValue = mode;
74
+ return this;
75
+ }
76
+
77
+ precision(digits: i32): this {
78
+ this.numericMode = true;
79
+ this.numericPrecisionValue = digits < 0 ? 0 : digits;
80
+ this.refreshNumericText();
81
+ return this;
82
+ }
83
+
84
+ prefix(value: string): this {
85
+ this.numericMode = true;
86
+ this.numericPrefixValue = value;
87
+ this.includeInCharset(value);
88
+ this.refreshNumericText();
89
+ return this;
90
+ }
91
+
92
+ suffix(value: string): this {
93
+ this.numericMode = true;
94
+ this.numericSuffixValue = value;
95
+ this.includeInCharset(value);
96
+ this.refreshNumericText();
97
+ return this;
98
+ }
99
+
100
+ setValue(value: f64): bool {
101
+ this.numericMode = true;
102
+ this.hasNumericValue = true;
103
+ this.numericValue = value;
104
+ return this.setText(this.composeNumericText(value));
105
+ }
106
+
107
+ textOverflow(mode: TextOverflow): this {
108
+ super.overflow(mode);
109
+ return this;
110
+ }
111
+
112
+ onReady(callback: (event: TextLayoutReadyEventArgs) => void): this {
113
+ super.onReady(callback);
114
+ return this;
115
+ }
116
+
117
+ onReadyWith<Owner>(owner: Owner, handler: TextLayoutReadyHandler<Owner>): this {
118
+ super.onReadyWith<Owner>(owner, handler);
119
+ return this;
120
+ }
121
+
122
+ width(value: f32, unit: Unit = Unit.Pixel): this {
123
+ super.width(value, unit);
124
+ return this;
125
+ }
126
+
127
+ height(value: f32, unit: Unit = Unit.Pixel): this {
128
+ super.height(value, unit);
129
+ return this;
130
+ }
131
+
132
+ fontStack(stack: FontStack, size: f32): this {
133
+ super.fontStack(stack, size);
134
+ return this;
135
+ }
136
+
137
+ fontFamily(family: FontFamily): this {
138
+ super.fontFamily(family);
139
+ return this;
140
+ }
141
+
142
+ fontWeight(weight: FontWeight): this {
143
+ super.fontWeight(weight);
144
+ return this;
145
+ }
146
+
147
+ fontStyle(style: FontStyle): this {
148
+ super.fontStyle(style);
149
+ return this;
150
+ }
151
+
152
+ fontSize(size: f32): this {
153
+ super.fontSize(size);
154
+ return this;
155
+ }
156
+
157
+ lineHeight(px: f32): this {
158
+ super.lineHeight(px);
159
+ return this;
160
+ }
161
+
162
+ color(color: u32): this {
163
+ super.color(color);
164
+ return this;
165
+ }
166
+
167
+ textColor(color: u32): this {
168
+ super.textColor(color);
169
+ return this;
170
+ }
171
+
172
+ textAlign(align: TextAlign): this {
173
+ super.textAlign(align);
174
+ return this;
175
+ }
176
+
177
+ verticalAlign(align: TextVerticalAlign): this {
178
+ super.verticalAlign(align);
179
+ return this;
180
+ }
181
+
182
+ maxLines(lines: i32): this {
183
+ super.maxLines(lines);
184
+ return this;
185
+ }
186
+
187
+ textLimits(maxChars: i32, maxLines: i32): this {
188
+ super.textLimits(maxChars, maxLines);
189
+ return this;
190
+ }
191
+
192
+ wrap(flag: bool = true): this {
193
+ super.wrap(flag);
194
+ return this;
195
+ }
196
+
197
+ wrapping(flag: bool = true): this {
198
+ super.wrapping(flag);
199
+ return this;
200
+ }
201
+
202
+ private supportsText(value: string): bool {
203
+ if (this.charsetValue.length == 0) {
204
+ return true;
205
+ }
206
+ for (let i = 0; i < value.length; i++) {
207
+ if (!this.charsetContains(value.charCodeAt(i))) {
208
+ return false;
209
+ }
210
+ }
211
+ return true;
212
+ }
213
+
214
+ private charsetContains(code: i32): bool {
215
+ for (let i = 0; i < this.charsetValue.length; i++) {
216
+ if (this.charsetValue.charCodeAt(i) == code) {
217
+ return true;
218
+ }
219
+ }
220
+ return false;
221
+ }
222
+
223
+ private includeInCharset(value: string): void {
224
+ for (let i = 0; i < value.length; i++) {
225
+ const code = value.charCodeAt(i);
226
+ if (!this.charsetContains(code)) {
227
+ this.charsetValue += value.charAt(i);
228
+ }
229
+ }
230
+ }
231
+
232
+ private refreshNumericText(): void {
233
+ if (!this.numericMode || !this.hasNumericValue) {
234
+ return;
235
+ }
236
+ this.setText(this.composeNumericText(this.numericValue));
237
+ }
238
+
239
+ private composeNumericText(value: f64): string {
240
+ this.includeInCharset(this.numericPrefixValue);
241
+ this.includeInCharset(this.numericSuffixValue);
242
+ return this.numericPrefixValue + this.formatNumericValue(value) + this.numericSuffixValue;
243
+ }
244
+
245
+ private formatNumericValue(value: f64): string {
246
+ if (value != value || !isFinite(value) || this.numericPrecisionValue < 0) {
247
+ return value.toString();
248
+ }
249
+
250
+ let scale: i64 = 1;
251
+ for (let i = 0; i < this.numericPrecisionValue; i++) {
252
+ scale *= 10;
253
+ }
254
+
255
+ const negative = value < 0.0;
256
+ const absValue = negative ? -value : value;
257
+ const scaled = <i64>Math.round(absValue * <f64>scale);
258
+ const whole = scaled / scale;
259
+ const fraction = scaled % scale;
260
+
261
+ let text = whole.toString();
262
+ if (this.numericPrecisionValue > 0) {
263
+ let fractionText = fraction.toString();
264
+ while (fractionText.length < this.numericPrecisionValue) {
265
+ fractionText = "0" + fractionText;
266
+ }
267
+ text += "." + fractionText;
268
+ }
269
+
270
+ if (negative) {
271
+ text = "-" + text;
272
+ }
273
+ return text;
274
+ }
275
+ }
@@ -0,0 +1,308 @@
1
+ import * as ui from "../bindings/ui";
2
+ import { LoadedEventArgs, onLoadedWith } from "../core/FrameScheduler";
3
+ import { error } from "../core/Logger";
4
+ import { Node } from "../core/Node";
5
+ import { FontFace, FontFamily, FontStack, FontStyle, FontWeight, FontsLoadedEventArgs } from "../core/Typography";
6
+ import { TextAlign, TextOverflow, TextVerticalAlign, Unit } from "../core/ffi";
7
+ import { RichText, RichTextSpan } from "../nodes/RichText";
8
+ import { Text } from "../nodes/Text";
9
+
10
+ export class TextLayoutReadyEventArgs {
11
+ readonly layout: TextLayout;
12
+
13
+ constructor(layout: TextLayout) {
14
+ this.layout = layout;
15
+ }
16
+ }
17
+
18
+ export type TextLayoutReadyHandler<Owner> = (owner: Owner, event: TextLayoutReadyEventArgs) => void;
19
+
20
+ export class TextMetrics {
21
+ constructor(
22
+ readonly width: f32 = 0.0,
23
+ readonly height: f32 = 0.0,
24
+ readonly baseline: f32 = 0.0,
25
+ readonly lineCount: i32 = 0,
26
+ readonly maxLineWidth: f32 = 0.0,
27
+ ) {}
28
+ }
29
+
30
+ class TextLayoutReadyCallback {
31
+ constructor(
32
+ private readonly layout: TextLayout,
33
+ private readonly callback: (event: TextLayoutReadyEventArgs) => void,
34
+ ) {}
35
+
36
+ handleReady(): void {
37
+ onLoadedWith<TextLayoutReadyCallback>(this, handleTextLayoutLoaded);
38
+ }
39
+
40
+ handleLoaded(): void {
41
+ this.layout._ensureBuiltForReady();
42
+ FontFace.whenFontsLoadedWith<TextLayoutReadyCallback>(
43
+ this.layout._requiredFontIdsForReady(),
44
+ this,
45
+ handleTextLayoutFontsReady,
46
+ );
47
+ }
48
+
49
+ handleFontsReady(): void {
50
+ this.layout._prepareNow();
51
+ this.callback(new TextLayoutReadyEventArgs(this.layout));
52
+ }
53
+ }
54
+
55
+ class TextLayoutReadyHandlerAction<Owner> {
56
+ constructor(
57
+ private readonly layout: TextLayout,
58
+ private readonly owner: Owner,
59
+ private readonly handler: TextLayoutReadyHandler<Owner>,
60
+ ) {}
61
+
62
+ handleReady(): void {
63
+ onLoadedWith<TextLayoutReadyHandlerAction<Owner>>(
64
+ this,
65
+ (action: TextLayoutReadyHandlerAction<Owner>, _event: LoadedEventArgs): void => {
66
+ action.handleLoaded();
67
+ },
68
+ );
69
+ }
70
+
71
+ handleLoaded(): void {
72
+ this.layout._ensureBuiltForReady();
73
+ FontFace.whenFontsLoadedWith<TextLayoutReadyHandlerAction<Owner>>(
74
+ this.layout._requiredFontIdsForReady(),
75
+ this,
76
+ (action: TextLayoutReadyHandlerAction<Owner>, _event: FontsLoadedEventArgs): void => {
77
+ action.handleFontsReady();
78
+ },
79
+ );
80
+ }
81
+
82
+ handleFontsReady(): void {
83
+ this.layout._prepareNow();
84
+ this.handler(this.owner, new TextLayoutReadyEventArgs(this.layout));
85
+ }
86
+ }
87
+
88
+ function handleTextLayoutReady(callback: TextLayoutReadyCallback): void {
89
+ callback.handleReady();
90
+ }
91
+
92
+ function handleTextLayoutLoaded(callback: TextLayoutReadyCallback, _event: LoadedEventArgs): void {
93
+ callback.handleLoaded();
94
+ }
95
+
96
+ function handleTextLayoutFontsReady(callback: TextLayoutReadyCallback, _event: FontsLoadedEventArgs): void {
97
+ callback.handleFontsReady();
98
+ }
99
+
100
+ /**
101
+ * Immediate-mode formatted text resource.
102
+ *
103
+ * Stage 3 backs this with the existing retained text preparation pipeline so it
104
+ * shares HarfBuzz shaping, fallback fonts, RichText style runs, and core glyph
105
+ * rendering with `Text`/`RichText`.
106
+ */
107
+ export class TextLayout {
108
+ private readonly nodeValue: Text;
109
+ private readyValue: bool = false;
110
+ private metricsValue: TextMetrics = new TextMetrics();
111
+
112
+ constructor(text: string = "", node: Text | null = null) {
113
+ this.nodeValue = node === null ? new Text(text) : changetype<Text>(node);
114
+ }
115
+
116
+ static text(text: string): TextLayout {
117
+ return new TextLayout(text);
118
+ }
119
+
120
+ static rich(fragments: Array<RichTextSpan>): TextLayout {
121
+ return new TextLayout("", new RichText(fragments));
122
+ }
123
+
124
+ get isReady(): bool {
125
+ return this.readyValue;
126
+ }
127
+
128
+ /** @internal */
129
+ _drawNode(): Node {
130
+ this.ensureBuilt();
131
+ return this.nodeValue;
132
+ }
133
+
134
+ /** @internal */
135
+ _prepareNow(): void {
136
+ this.ensureBuilt();
137
+ const prepared = ui.prepareNode(this.nodeValue.builtHandle);
138
+ if (prepared == 0) {
139
+ this.readyValue = false;
140
+ this.metricsValue = new TextMetrics();
141
+ return;
142
+ }
143
+ const metrics = ui.tryGetTextMetrics(this.nodeValue.builtHandle);
144
+ if (metrics === null) {
145
+ this.metricsValue = new TextMetrics();
146
+ } else {
147
+ this.metricsValue = new TextMetrics(
148
+ unchecked(metrics[0]),
149
+ unchecked(metrics[1]),
150
+ unchecked(metrics[2]),
151
+ <i32>unchecked(metrics[3]),
152
+ unchecked(metrics[4]),
153
+ );
154
+ }
155
+ this.readyValue = true;
156
+ }
157
+
158
+ measure(): TextMetrics {
159
+ if (!this.readyValue) {
160
+ error("TextLayout", "TextLayout.measure() called before the TextLayout was ready; register onReady/onReadyWith and measure after the callback.");
161
+ return new TextMetrics();
162
+ }
163
+ return this.metricsValue;
164
+ }
165
+
166
+ get measuredWidth(): f32 {
167
+ return this.measure().width;
168
+ }
169
+
170
+ get measuredHeight(): f32 {
171
+ return this.measure().height;
172
+ }
173
+
174
+ onReady(callback: (event: TextLayoutReadyEventArgs) => void): this {
175
+ const ready = new TextLayoutReadyCallback(this, callback);
176
+ handleTextLayoutReady(ready);
177
+ return this;
178
+ }
179
+
180
+ onReadyWith<Owner>(owner: Owner, handler: TextLayoutReadyHandler<Owner>): this {
181
+ const ready = new TextLayoutReadyHandlerAction<Owner>(this, owner, handler);
182
+ ready.handleReady();
183
+ return this;
184
+ }
185
+
186
+ text(value: string): this {
187
+ this.nodeValue.text(value);
188
+ this.markDirty();
189
+ return this;
190
+ }
191
+
192
+ width(value: f32, unit: Unit = Unit.Pixel): this {
193
+ this.nodeValue.width(value, unit);
194
+ this.markDirty();
195
+ return this;
196
+ }
197
+
198
+ height(value: f32, unit: Unit = Unit.Pixel): this {
199
+ this.nodeValue.height(value, unit);
200
+ this.markDirty();
201
+ return this;
202
+ }
203
+
204
+ fontStack(stack: FontStack, size: f32): this {
205
+ this.nodeValue.fontStack(stack, size);
206
+ this.markDirty();
207
+ return this;
208
+ }
209
+
210
+ fontFamily(family: FontFamily): this {
211
+ this.nodeValue.fontFamily(family);
212
+ this.markDirty();
213
+ return this;
214
+ }
215
+
216
+ fontWeight(weight: FontWeight): this {
217
+ this.nodeValue.fontWeight(weight);
218
+ this.markDirty();
219
+ return this;
220
+ }
221
+
222
+ fontStyle(style: FontStyle): this {
223
+ this.nodeValue.fontStyle(style);
224
+ this.markDirty();
225
+ return this;
226
+ }
227
+
228
+ fontSize(size: f32): this {
229
+ this.nodeValue.fontSize(size);
230
+ this.markDirty();
231
+ return this;
232
+ }
233
+
234
+ lineHeight(px: f32): this {
235
+ this.nodeValue.lineHeight(px);
236
+ this.markDirty();
237
+ return this;
238
+ }
239
+
240
+ color(color: u32): this {
241
+ this.nodeValue.textColor(color);
242
+ this.markDirty();
243
+ return this;
244
+ }
245
+
246
+ textColor(color: u32): this {
247
+ return this.color(color);
248
+ }
249
+
250
+ textAlign(align: TextAlign): this {
251
+ this.nodeValue.textAlign(align);
252
+ this.markDirty();
253
+ return this;
254
+ }
255
+
256
+ verticalAlign(align: TextVerticalAlign): this {
257
+ this.nodeValue.verticalAlign(align);
258
+ this.markDirty();
259
+ return this;
260
+ }
261
+
262
+ maxLines(lines: i32): this {
263
+ this.nodeValue.maxLines(lines);
264
+ this.markDirty();
265
+ return this;
266
+ }
267
+
268
+ textLimits(maxChars: i32, maxLines: i32): this {
269
+ this.nodeValue.textLimits(maxChars, maxLines);
270
+ this.markDirty();
271
+ return this;
272
+ }
273
+
274
+ wrap(flag: bool = true): this {
275
+ this.nodeValue.wrapping(flag);
276
+ this.markDirty();
277
+ return this;
278
+ }
279
+
280
+ wrapping(flag: bool = true): this {
281
+ return this.wrap(flag);
282
+ }
283
+
284
+ overflow(mode: TextOverflow): this {
285
+ this.nodeValue.overflow(mode);
286
+ this.markDirty();
287
+ return this;
288
+ }
289
+
290
+ private ensureBuilt(): void {
291
+ this.nodeValue.build();
292
+ }
293
+
294
+ /** @internal */
295
+ _ensureBuiltForReady(): void {
296
+ this.ensureBuilt();
297
+ }
298
+
299
+ /** @internal */
300
+ _requiredFontIdsForReady(): Array<u32> {
301
+ return this.nodeValue._requiredFontIds();
302
+ }
303
+
304
+ private markDirty(): void {
305
+ this.readyValue = false;
306
+ this.metricsValue = new TextMetrics();
307
+ }
308
+ }
@@ -1,8 +1,6 @@
1
1
  import {
2
2
  fui_worker_complete_string,
3
- fui_worker_copy_input,
4
3
  fui_worker_fail,
5
- fui_worker_input_length,
6
4
  fui_worker_is_cancelled,
7
5
  fui_worker_request_yield,
8
6
  fui_worker_request_yield_delay,
@@ -10,45 +8,21 @@ import {
10
8
  } from "./ffi";
11
9
  import { handleFetchComplete, handleFetchError } from "../core/Fetch";
12
10
 
13
- let inputRead = false;
14
- let inputCache = "";
15
11
  let terminalSent = false;
16
- let testInputOverride: string | null = null;
17
12
  const WORKER_CALLBACK_BUFFER = new Uint8Array(1024 * 1024);
18
13
 
19
14
  function encodeUtf8(text: string): Uint8Array {
20
15
  return Uint8Array.wrap(String.UTF8.encode(text, false));
21
16
  }
22
17
 
23
- function readInputMessage(): string {
24
- if (testInputOverride !== null) {
25
- return changetype<string>(testInputOverride);
26
- }
27
- const byteLength = fui_worker_input_length();
28
- if (byteLength == 0) {
29
- return "";
30
- }
31
- const bytes = new Uint8Array(byteLength);
32
- const copied = fui_worker_copy_input(bytes.dataStart, <u32>bytes.length);
33
- if (copied == 0) {
34
- return "";
35
- }
36
- return String.UTF8.decodeUnsafe(bytes.dataStart, <usize>copied, false);
37
- }
38
-
39
18
  function sendText(text: string, callback: (ptr: usize, len: u32) => void): void {
40
19
  const bytes = encodeUtf8(text);
41
20
  callback(bytes.length > 0 ? bytes.dataStart : 0, <u32>bytes.length);
42
21
  }
43
22
 
44
23
  export class Worker {
45
- static receiveMessage(): string {
46
- if (inputRead) {
47
- return inputCache;
48
- }
49
- inputCache = readInputMessage();
50
- inputRead = true;
51
- return inputCache;
24
+ static entry(inputPtr: usize, inputLen: u32, handler: (input: string) => void): void {
25
+ handler(inputPtr == 0 || inputLen == 0 ? "" : String.UTF8.decodeUnsafe(inputPtr, <usize>inputLen, false));
52
26
  }
53
27
 
54
28
  static reportProgress(progress: string): void {
@@ -157,13 +131,6 @@ export function __fui_on_fetch_error(requestId: u32, payloadPtr: usize, payloadL
157
131
  );
158
132
  }
159
133
 
160
- export function __resetWorkerRuntimeForTests(): void {
161
- inputRead = false;
162
- inputCache = "";
134
+ export function resetWorkerRuntime(): void {
163
135
  terminalSent = false;
164
- testInputOverride = null;
165
- }
166
-
167
- export function __setWorkerInputForTests(value: string): void {
168
- testInputOverride = value;
169
136
  }
@@ -4,8 +4,8 @@ export abstract class WorkerJob {
4
4
  private started: bool = false;
5
5
  private finished: bool = false;
6
6
 
7
- static resume<T extends WorkerJob>(job: T): T | null {
8
- job.ensureStarted();
7
+ static resume<T extends WorkerJob>(job: T, input: string = ""): T | null {
8
+ job.ensureStarted(input);
9
9
  if (job.finished) {
10
10
  return null;
11
11
  }
@@ -13,14 +13,10 @@ export abstract class WorkerJob {
13
13
  return job.finished ? null : job;
14
14
  }
15
15
 
16
- protected onStart(): void {}
16
+ protected onStart(input: string): void {}
17
17
 
18
18
  abstract run(): void;
19
19
 
20
- protected receiveMessage(): string {
21
- return Worker.receiveMessage();
22
- }
23
-
24
20
  protected reportProgress(progress: string): void {
25
21
  if (this.finished) {
26
22
  return;
@@ -55,11 +51,11 @@ export abstract class WorkerJob {
55
51
  return Worker.yield(delayMs);
56
52
  }
57
53
 
58
- private ensureStarted(): void {
54
+ private ensureStarted(input: string): void {
59
55
  if (this.started) {
60
56
  return;
61
57
  }
62
58
  this.started = true;
63
- this.onStart();
59
+ this.onStart(input);
64
60
  }
65
61
  }
package/src/worker/ffi.ts CHANGED
@@ -1,9 +1,3 @@
1
- @external("fui_worker_host", "fui_worker_input_length")
2
- export declare function fui_worker_input_length(): u32;
3
-
4
- @external("fui_worker_host", "fui_worker_copy_input")
5
- export declare function fui_worker_copy_input(ptr: usize, capacity: u32): u32;
6
-
7
1
  @external("fui_worker_host", "fui_worker_report_progress")
8
2
  export declare function fui_worker_report_progress(ptr: usize, len: u32): void;
9
3