@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
@@ -1 +1 @@
1
- export * from './src/routed-app-conventions';
1
+ export * from '../../browser-bridge/src/routed-app-conventions.js';
@@ -1,27 +1 @@
1
- export type {
2
- HarnessAppOptions,
3
- HarnessContext,
4
- HarnessController,
5
- HarnessDebugApi,
6
- HarnessExports,
7
- HarnessNavigationMode,
8
- HarnessOptions,
9
- HarnessState,
10
- ManagedHarnessOptions,
11
- ManagedHistoryState,
12
- } from './common-harness/types';
13
-
14
- export {
15
- canManagedNavigateBack,
16
- canManagedNavigateForward,
17
- pushManagedHistoryEntry,
18
- readManagedHistoryState,
19
- replaceManagedHistoryEntry,
20
- setCurrentManagedHistorySnapshotId,
21
- syncManagedHistoryPop,
22
- } from './common-harness/managed-history';
23
-
24
- export {
25
- startHarness,
26
- startManagedHarness,
27
- } from './common-harness/managed-harness';
1
+ export * from './shared-browser';
@@ -8,7 +8,7 @@ export {
8
8
  replaceManagedHistoryEntry,
9
9
  setCurrentManagedHistorySnapshotId,
10
10
  syncManagedHistoryPop,
11
- } from './common-harness';
11
+ } from './shared-browser';
12
12
 
13
13
  export type {
14
14
  HarnessAppOptions,
@@ -21,30 +21,17 @@ export type {
21
21
  HarnessState,
22
22
  ManagedHarnessOptions,
23
23
  ManagedHistoryState,
24
- } from './common-harness';
25
-
26
- export {
27
- buildRoutedHarnessRoutes,
28
- defineRoutedAppManifest,
29
- renderRoutedPageHead,
30
- resolveRouteManifest,
31
- resolveRoutePath,
32
- routeDef,
33
- routeHead,
34
- } from './routed-app-conventions';
24
+ } from './shared-browser';
35
25
 
36
26
  export {
37
27
  startRoutedHarness,
38
28
  } from './routed-harness';
39
29
 
40
- export type {
41
- RoutedAppHeadTag,
42
- RoutedAppRoute,
43
- RoutedAppRouteDefinition,
44
- RoutedAppRouteManifest,
45
- ResolvedRoutedAppRoute,
46
- ResolvedRoutedAppRouteManifest,
47
- } from './routed-app-conventions';
30
+ export {
31
+ BuildMode,
32
+ DevToolsDomMirrorMode,
33
+ PageZoomMode,
34
+ } from '@effindomv2/runtime';
48
35
 
49
36
  export type {
50
37
  RoutedHarnessConfig,
@@ -53,24 +40,30 @@ export type {
53
40
  } from './routed-harness';
54
41
 
55
42
  export type {
43
+ RoutedAppHeadTag,
44
+ RoutedAppRoute,
45
+ RoutedAppRouteDefinition,
46
+ RoutedAppRouteManifest,
47
+ ResolvedRoutedAppRoute,
48
+ ResolvedRoutedAppRouteManifest,
56
49
  RoutedHarnessRouteSpec,
57
- } from './routed-app-conventions';
50
+ } from './shared-browser';
58
51
 
59
52
  export {
60
53
  defineHostEvents,
61
54
  hostEvent,
62
- } from './host-events';
55
+ } from './shared-browser';
63
56
 
64
57
  export type {
65
58
  HostEventMethodDefinition,
66
59
  HostEventsDefinition,
67
60
  NormalizedHostEventMethod,
68
- } from './host-events';
61
+ } from './shared-browser';
69
62
 
70
63
  export {
71
64
  defineHostServices,
72
65
  hostService,
73
- } from './host-services';
66
+ } from './shared-browser';
74
67
 
75
68
  export type {
76
69
  HostServiceImportIo,
@@ -78,8 +71,8 @@ export type {
78
71
  HostServiceTypeName,
79
72
  HostServicesDefinition,
80
73
  NormalizedHostServiceMethod,
81
- } from './host-services';
74
+ } from './shared-browser';
82
75
 
83
76
  export type {
84
77
  WorkerHostServicesBundleConfig,
85
- } from './worker-types';
78
+ } from './shared-browser';
@@ -1,194 +1 @@
1
- import {
2
- pushManagedHistoryEntry,
3
- replaceManagedHistoryEntry,
4
- startManagedHarness,
5
- type HarnessAppOptions,
6
- type HarnessController,
7
- type HarnessExports,
8
- type HarnessState,
9
- } from './common-harness';
10
- import type { HostEventsDefinition } from './host-events';
11
- import type { HostServicesDefinition } from './host-services';
12
- import type { WorkerHostServicesBundleConfig } from './worker-types';
13
- import type { RoutedHarnessRouteSpec } from './routed-app-conventions';
14
-
15
- type NavigationMode = 'push' | 'replace' | 'pop';
16
-
17
- declare global {
18
- interface Window {
19
- __fuiAsReady?: boolean;
20
- __fuiAsError?: string;
21
- }
22
- }
23
-
24
- export type RoutedHarnessRoute = RoutedHarnessRouteSpec & {
25
- readonly matchPath?: string;
26
- };
27
-
28
- export interface RoutedHarnessManagerState {
29
- readonly shellId: string;
30
- readonly routePath: string;
31
- readonly activeWasmPath: string;
32
- readonly routeLoads: Readonly<Record<string, number>>;
33
- }
34
-
35
- export interface RoutedHarnessConfig<
36
- TExports extends HarnessExports,
37
- TRoute extends RoutedHarnessRoute = RoutedHarnessRoute,
38
- > {
39
- readonly shellId: string;
40
- readonly routeBase: string;
41
- readonly routes: readonly TRoute[];
42
- readonly hostEvents?: HostEventsDefinition;
43
- readonly hostServices?: HostServicesDefinition;
44
- readonly workerHostServices?: WorkerHostServicesBundleConfig;
45
- readonly recreateRuntimeOnWarmRouteSwap?: boolean;
46
- readonly showLoadingOverlay?: (isWarmRouteSwap: boolean, route: TRoute) => boolean | undefined;
47
- readonly onBooting?: () => void;
48
- readonly onRouteLoading?: (route: TRoute) => void;
49
- readonly onRouteReady?: (state: RoutedHarnessManagerState, route: TRoute) => void;
50
- readonly onHarnessStateUpdated?: (state: HarnessState) => void;
51
- readonly onHarnessError?: (error: unknown) => void;
52
- readonly run: (exports: TExports, route: TRoute) => void;
53
- readonly onDispose?: (exports: TExports, route: TRoute) => void;
54
- }
55
-
56
- function normalizeRoutePath(
57
- pathname: string,
58
- routeBase: string,
59
- routeByPath: ReadonlyMap<string, RoutedHarnessRoute>,
60
- fallbackRoutePath: string,
61
- ): string {
62
- let normalized = pathname;
63
- if (normalized.endsWith('/index.html')) {
64
- normalized = normalized.slice(0, -'index.html'.length);
65
- }
66
- if (!normalized.endsWith('/')) {
67
- normalized += '/';
68
- }
69
- if (normalized === routeBase) {
70
- return fallbackRoutePath;
71
- }
72
- return routeByPath.has(normalized) ? normalized : fallbackRoutePath;
73
- }
74
-
75
- function resolveRouteMatchPath(route: RoutedHarnessRoute): string {
76
- return route.matchPath ?? route.routePath;
77
- }
78
-
79
- function currentBrowserPath(): string {
80
- let pathname = window.location.pathname;
81
- if (pathname.endsWith('/index.html')) {
82
- pathname = pathname.slice(0, -'index.html'.length);
83
- }
84
- return pathname.endsWith('/') ? pathname : `${pathname}/`;
85
- }
86
-
87
- export function startRoutedHarness<
88
- TExports extends HarnessExports,
89
- TRoute extends RoutedHarnessRoute = RoutedHarnessRoute,
90
- >(config: RoutedHarnessConfig<TExports, TRoute>): void {
91
- const routeByPath = new Map<string, TRoute>(config.routes.map((route) => [resolveRouteMatchPath(route), route]));
92
- const fallbackRoute = config.routes[0];
93
- const routeLoads: Record<string, number> = {};
94
- let activeRoute: TRoute | null = null;
95
- let navigationQueue: Promise<void> = Promise.resolve();
96
-
97
- if (fallbackRoute === undefined) {
98
- throw new Error('startRoutedHarness requires at least one route.');
99
- }
100
-
101
- function resolveRoute(pathname: string): TRoute {
102
- const normalizedPath = normalizeRoutePath(
103
- pathname,
104
- config.routeBase,
105
- routeByPath,
106
- resolveRouteMatchPath(fallbackRoute),
107
- );
108
- return routeByPath.get(normalizedPath) ?? fallbackRoute;
109
- }
110
-
111
- function sameBrowserLocation(route: TRoute): boolean {
112
- return currentBrowserPath() === resolveRouteMatchPath(route);
113
- }
114
-
115
- function buildManagerState(route: TRoute): RoutedHarnessManagerState {
116
- return {
117
- shellId: config.shellId,
118
- routePath: route.routePath,
119
- activeWasmPath: route.wasmPath,
120
- routeLoads: { ...routeLoads },
121
- };
122
- }
123
-
124
- async function navigateToRoute(
125
- controller: HarnessController,
126
- targetUrl: URL,
127
- mode: NavigationMode,
128
- ): Promise<void> {
129
- const route = resolveRoute(targetUrl.pathname);
130
- if (mode !== 'pop' && sameBrowserLocation(route) && activeRoute?.routePath === route.routePath) {
131
- config.onRouteReady?.(buildManagerState(route), route);
132
- window.__fuiAsReady = true;
133
- delete window.__fuiAsError;
134
- return;
135
- }
136
-
137
- const destination = new URL(route.routePath, window.location.origin);
138
- destination.search = targetUrl.search;
139
- destination.hash = targetUrl.hash;
140
- if (mode === 'push') {
141
- pushManagedHistoryEntry(destination);
142
- } else if (mode === 'replace' && !sameBrowserLocation(route)) {
143
- replaceManagedHistoryEntry(destination);
144
- }
145
-
146
- window.__fuiAsReady = false;
147
- config.onRouteLoading?.(route);
148
- const isWarmRouteSwap = activeRoute !== null;
149
- if (isWarmRouteSwap && config.recreateRuntimeOnWarmRouteSwap === true) {
150
- await controller.recreateRuntime();
151
- }
152
-
153
- const appOptions: HarnessAppOptions<TExports> = {
154
- wasmPath: route.wasmPath,
155
- persistedRestoreMode: activeRoute === null ? 'initial' : (mode === 'pop' ? 'pop' : 'none'),
156
- hostEvents: config.hostEvents,
157
- hostServices: config.hostServices,
158
- workerHostServices: config.workerHostServices,
159
- run(exports): void {
160
- config.run(exports, route);
161
- },
162
- onDispose(exports): void {
163
- config.onDispose?.(exports, route);
164
- },
165
- onStateUpdated(state): void {
166
- config.onHarnessStateUpdated?.(state);
167
- },
168
- };
169
- const showLoadingOverlay = config.showLoadingOverlay?.(isWarmRouteSwap, route);
170
- appOptions.showLoadingOverlay = showLoadingOverlay ?? !isWarmRouteSwap;
171
-
172
- await controller.loadApp(appOptions);
173
- routeLoads[route.routePath] = (routeLoads[route.routePath] ?? 0) + 1;
174
- activeRoute = route;
175
- config.onRouteReady?.(buildManagerState(route), route);
176
- window.__fuiAsReady = true;
177
- delete window.__fuiAsError;
178
- }
179
-
180
- startManagedHarness({
181
- onReady: async (controller): Promise<void> => {
182
- controller.setSameOriginNavigationHandler((target, mode) => {
183
- navigationQueue = navigationQueue.then(() => navigateToRoute(controller, target, mode));
184
- return navigationQueue;
185
- });
186
-
187
- config.onBooting?.();
188
- await navigateToRoute(controller, new URL(window.location.href), 'replace');
189
- },
190
- onError(error): void {
191
- config.onHarnessError?.(error);
192
- },
193
- });
194
- }
1
+ export * from './shared-browser';
@@ -0,0 +1,6 @@
1
+ export * from '../../../browser-bridge/src/managed-harness.js';
2
+ export * from '../../../browser-bridge/src/managed-harness/abi-version.js';
3
+ export * from '../../../browser-bridge/src/managed-harness/persisted-restore-policy.js';
4
+ export * from '../../../browser-bridge/src/managed-harness/ui-chrome.js';
5
+ export * from '../../../browser-bridge/src/routed-app-conventions.js';
6
+ export * from '../../../browser-bridge/src/routed-harness.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@effindomv2/fui-as",
3
- "version": "0.1.36",
3
+ "version": "0.1.39",
4
4
  "private": false,
5
5
  "license": "AGPL-3.0-only OR LicenseRef-EffinDom-Commercial",
6
6
  "description": "EffinDom v2 AssemblyScript frontend framework SDK and browser harness",
@@ -45,21 +45,25 @@
45
45
  "types": "./browser/src/common-harness.ts",
46
46
  "default": "./browser/src/common-harness.ts"
47
47
  },
48
+ "./browser/shared-browser": {
49
+ "types": "./browser/src/shared-browser.ts",
50
+ "default": "./browser/src/shared-browser.ts"
51
+ },
48
52
  "./browser/routed-harness": {
49
53
  "types": "./browser/src/routed-harness.ts",
50
54
  "default": "./browser/src/routed-harness.ts"
51
55
  },
52
56
  "./browser/host-events": {
53
- "types": "./browser/src/host-events.ts",
54
- "default": "./browser/src/host-events.ts"
57
+ "types": "./browser/src/shared-browser.ts",
58
+ "default": "./browser/src/shared-browser.ts"
55
59
  },
56
60
  "./browser/host-services": {
57
- "types": "./browser/src/host-services.ts",
58
- "default": "./browser/src/host-services.ts"
61
+ "types": "./browser/src/shared-browser.ts",
62
+ "default": "./browser/src/shared-browser.ts"
59
63
  },
60
64
  "./browser/worker-types": {
61
- "types": "./browser/src/worker-types.ts",
62
- "default": "./browser/src/worker-types.ts"
65
+ "types": "./browser/src/shared-browser.ts",
66
+ "default": "./browser/src/shared-browser.ts"
63
67
  }
64
68
  },
65
69
  "files": [
@@ -76,26 +80,32 @@
76
80
  ],
77
81
  "scripts": {
78
82
  "guard:runtime-dependency": "bash scripts/check-runtime-dependency.sh",
83
+ "generate:abi": "mkdir -p build && esbuild ../abi/generate.ts --bundle --format=esm --platform=node --target=node20 --packages=external --outfile=build/generate-abi.mjs && node build/generate-abi.mjs fui-as-ui && node build/generate-abi.mjs fui-as-host && node build/generate-abi.mjs fui-as-enums",
84
+ "check:abi": "mkdir -p build && esbuild ../abi/generate.ts --bundle --format=esm --platform=node --target=node20 --packages=external --outfile=build/generate-abi.mjs && node build/generate-abi.mjs fui-as-ui --check && node build/generate-abi.mjs fui-as-host --check && node build/generate-abi.mjs fui-as-enums --check",
85
+ "generate:ui-abi": "npm run generate:abi",
86
+ "check:ui-abi": "npm run check:abi",
79
87
  "build": "npm run guard:runtime-dependency && bash scripts/build.sh",
80
88
  "build:only": "npm run guard:runtime-dependency && bash scripts/build.sh",
81
89
  "build:full": "npm run guard:runtime-dependency && bash scripts/build.sh",
82
90
  "build:demo:as": "bash scripts/build-demo-as.sh",
91
+ "lint": "cd ../.. && npm run lint:v2",
92
+ "prepublishOnly": "npm run check:abi && npm run lint && npm run typecheck",
83
93
  "test:unit": "npm run guard:runtime-dependency && asp --verbose -c as-pect.config.mjs -a as-pect.asconfig.json",
84
- "test:integration": "npm run build:full && playwright test -c playwright.config.ts",
85
- "typecheck": "npm run guard:runtime-dependency && tsc -p tsconfig.json --noEmit"
94
+ "test:integration": "npm --prefix ../.. run build:v2:browser-bridge && npm run build:full && playwright test -c playwright.config.ts",
95
+ "typecheck": "npm run guard:runtime-dependency && npm run check:abi && tsc -p tsconfig.json --noEmit"
86
96
  },
87
97
  "dependencies": {
88
- "@assemblyscript/loader": "^0.28.17",
89
- "@devcycle/assemblyscript-json": "^2.0.0",
90
- "@effindomv2/runtime": "0.1.17"
98
+ "@assemblyscript/loader": "^0.28.19",
99
+ "@effindomv2/runtime": "0.1.20"
91
100
  },
92
101
  "devDependencies": {
93
- "@as-pect/assembly": "8.1.0",
94
- "@as-pect/cli": "8.1.0",
95
- "@as-pect/core": "8.1.0",
102
+ "@as-pect/assembly": "9.0.0",
103
+ "@as-pect/cli": "9.0.0",
104
+ "@as-pect/core": "9.0.0",
96
105
  "@playwright/test": "1.59.1",
97
106
  "@types/node": "^24.10.1",
98
- "assemblyscript": "0.28.17",
107
+ "assemblyscript": "0.28.19",
108
+ "@devcycle/assemblyscript-json": "2.0.0",
99
109
  "esbuild": "^0.27.7",
100
110
  "typescript": "^5.9.3"
101
111
  }
package/scripts/build.sh CHANGED
@@ -13,11 +13,11 @@ WORKER_BOOTSTRAP_BUILD="${PACKAGE_DIR}/build/worker-bootstrap.js"
13
13
  WORKER_BOOTSTRAP_MAP_BUILD="${PACKAGE_DIR}/build/worker-bootstrap.js.map"
14
14
  WORKER_HOST_SERVICES_BUILD="${PACKAGE_DIR}/build/worker-host-services.js"
15
15
  WORKER_HOST_SERVICES_MAP_BUILD="${PACKAGE_DIR}/build/worker-host-services.js.map"
16
- WORKER_MANIFEST_BUILD="${PACKAGE_DIR}/build/worker-manifest.json"
17
16
  FILE_PROCESSING_WORKER_BUILD="${PACKAGE_DIR}/build/file-processing-worker.js"
18
17
  FILE_PROCESSING_WORKER_MAP_BUILD="${PACKAGE_DIR}/build/file-processing-worker.js.map"
19
18
  HOST_SERVICE_GENERATOR_BUILD="${PACKAGE_DIR}/build/generate-host-services.mjs"
20
19
  HOST_EVENT_GENERATOR_BUILD="${PACKAGE_DIR}/build/generate-host-events.mjs"
20
+ ABI_GENERATOR_BUILD="${PACKAGE_DIR}/build/generate-abi.mjs"
21
21
  RUNTIME_CONFIG_FILE="effindom-runtime-config.js"
22
22
  DEFAULT_MANIFEST_PATH="./runtime/dist/effindom.v2.manifest.json"
23
23
  LOADING_OVERLAY_STYLES_FILE="${PACKAGE_DIR}/browser/loading-overlay-styles.html"
@@ -37,6 +37,30 @@ else
37
37
  exit 1
38
38
  fi
39
39
 
40
+ ESBUILD_RUNTIME_ALIAS_ARGS=()
41
+ if [ -f "${REPO_ROOT}/v2/browser-bridge/src/index.ts" ]; then
42
+ ESBUILD_RUNTIME_ALIAS_ARGS+=(
43
+ "--alias:@effindomv2/runtime=${REPO_ROOT}/v2/browser-bridge/src/index.ts"
44
+ "--alias:@effindomv2/runtime/core-types=${REPO_ROOT}/v2/browser-bridge/src/core-types.ts"
45
+ )
46
+ fi
47
+
48
+ generate_abi() {
49
+ npx esbuild "${REPO_ROOT}/v2/abi/generate.ts" \
50
+ --bundle \
51
+ --format=esm \
52
+ --platform=node \
53
+ --target=node20 \
54
+ --packages=external \
55
+ --outfile="${ABI_GENERATOR_BUILD}"
56
+
57
+ node "${ABI_GENERATOR_BUILD}" fui-as-ui
58
+ node "${ABI_GENERATOR_BUILD}" fui-as-host
59
+ node "${ABI_GENERATOR_BUILD}" fui-as-enums
60
+ }
61
+
62
+ generate_abi
63
+
40
64
  "${TSC_BIN}" -p tsconfig.json --noEmit
41
65
 
42
66
  build_app() {
@@ -119,6 +143,10 @@ find_worker_entries() {
119
143
 
120
144
  resolve_runtime_dist_dir() {
121
145
  local candidate=""
146
+ local public_runtime_dir="${REPO_ROOT}/public/v2/browser-bridge"
147
+ local package_runtime_dir="${REPO_ROOT}/v2/browser-bridge/dist"
148
+ local public_manifest="${public_runtime_dir}/effindom.v2.manifest.json"
149
+ local package_manifest="${package_runtime_dir}/effindom.v2.manifest.json"
122
150
  local candidates=()
123
151
 
124
152
  if [ -n "${EFFINDOM_RUNTIME_DIST_DIR:-}" ]; then
@@ -126,12 +154,18 @@ resolve_runtime_dist_dir() {
126
154
  fi
127
155
 
128
156
  candidates+=(
129
- "${REPO_ROOT}/public/v2/browser-bridge"
130
- "${REPO_ROOT}/v2/browser-bridge/dist"
157
+ "${public_runtime_dir}"
158
+ "${package_runtime_dir}"
131
159
  "${PACKAGE_DIR}/node_modules/@effindomv2/runtime/dist"
132
160
  "${REPO_ROOT}/node_modules/@effindomv2/runtime/dist"
133
161
  )
134
162
 
163
+ if [ -f "${public_manifest}" ] && [ -f "${package_manifest}" ] && ! cmp -s "${public_manifest}" "${package_manifest}"; then
164
+ echo "Note: using ${public_runtime_dir} for monorepo runtime assets." >&2
165
+ echo " ${package_runtime_dir} is a staged package copy and may be stale." >&2
166
+ echo " For ABI changes, run repo-root ./build.sh (or npm run build:v2:abi)." >&2
167
+ fi
168
+
135
169
  for candidate in "${candidates[@]}"; do
136
170
  if [ -f "${candidate}/bridge.js" ] && [ -f "${candidate}/effindom.v2.manifest.json" ] && [ -d "${candidate}/runtime" ]; then
137
171
  printf '%s\n' "${candidate}"
@@ -144,8 +178,9 @@ resolve_runtime_dist_dir() {
144
178
  echo " - \$EFFINDOM_RUNTIME_DIST_DIR" >&2
145
179
  echo " - ${PACKAGE_DIR}/node_modules/@effindomv2/runtime/dist" >&2
146
180
  echo " - ${REPO_ROOT}/node_modules/@effindomv2/runtime/dist" >&2
147
- echo " - ${REPO_ROOT}/v2/browser-bridge/dist" >&2
148
181
  echo " - ${REPO_ROOT}/public/v2/browser-bridge" >&2
182
+ echo " - ${REPO_ROOT}/v2/browser-bridge/dist" >&2
183
+ echo "Monorepo note: repo-root ./build.sh (or npm run build:v2:abi) refreshes the runtime assets used here." >&2
149
184
  echo "Install @effindomv2/runtime or build runtime assets first." >&2
150
185
  exit 1
151
186
  }
@@ -158,7 +193,8 @@ write_runtime_config() {
158
193
 
159
194
  cat > "${destination}/${RUNTIME_CONFIG_FILE}" <<EOF
160
195
  window.__effindomRuntime = Object.assign({}, window.__effindomRuntime, {
161
- manifestUrl: '${manifest_url}',
196
+ manifestUrl: new URL('${manifest_url}', document.currentScript && document.currentScript.src ? document.currentScript.src : document.baseURI).toString(),
197
+ buildMode: 'debug',
162
198
  });
163
199
  EOF
164
200
  }
@@ -222,43 +258,6 @@ build_workers() {
222
258
  done < <(find_worker_entries)
223
259
  }
224
260
 
225
- write_worker_manifest() {
226
- local tmp_entries
227
- tmp_entries="$(mktemp)"
228
- local worker_entry=""
229
- while IFS= read -r worker_entry; do
230
- [ -n "${worker_entry}" ] || continue
231
- local worker_name
232
- worker_name="$(basename "${worker_entry}" .ts)"
233
- local export_name=""
234
- while IFS= read -r export_name; do
235
- [ -n "${export_name}" ] || continue
236
- if grep -q "^${export_name} " "${tmp_entries}" 2>/dev/null; then
237
- echo "Duplicate worker export name: ${export_name}" >&2
238
- rm -f "${tmp_entries}"
239
- exit 1
240
- fi
241
- echo "${export_name} ./workers/${worker_name}.wasm" >> "${tmp_entries}"
242
- done < <(rg 'export function ([A-Za-z_][A-Za-z0-9_]*)\s*\(' "${worker_entry}" -or '$1')
243
- done < <(find_worker_entries)
244
-
245
- {
246
- printf '{\n "version": 1,\n "entries": {\n'
247
- local first=1
248
- local line=""
249
- sort "${tmp_entries}" | while IFS=' ' read -r entry_name entry_path; do
250
- [ -n "${entry_name}" ] || continue
251
- if [ "${first}" -eq 0 ]; then
252
- printf ',\n'
253
- fi
254
- first=0
255
- printf ' "%s": "%s"' "${entry_name}" "${entry_path}"
256
- done
257
- printf '\n }\n}\n'
258
- } > "${WORKER_MANIFEST_BUILD}"
259
- rm -f "${tmp_entries}"
260
- }
261
-
262
261
  copy_worker_assets() {
263
262
  local destination="$1"
264
263
  rm -rf "${destination}/workers"
@@ -273,7 +272,6 @@ copy_worker_assets() {
273
272
  cp "${WORKER_BOOTSTRAP_MAP_BUILD}" "${destination}/worker-bootstrap.js.map"
274
273
  cp "${WORKER_HOST_SERVICES_BUILD}" "${destination}/worker-host-services.js"
275
274
  cp "${WORKER_HOST_SERVICES_MAP_BUILD}" "${destination}/worker-host-services.js.map"
276
- cp "${WORKER_MANIFEST_BUILD}" "${destination}/worker-manifest.json"
277
275
  }
278
276
 
279
277
  generate_host_services "demo/src/host-services.ts" "demoHostServices" "demo/src/generated/HostServices.ts"
@@ -287,8 +285,8 @@ build_app "demo/src/routes/demo_home.ts" "${DEMO_OUT_DIR}/home.wasm"
287
285
  build_app "demo/src/routes/demo_advanced_controls.ts" "${DEMO_OUT_DIR}/advanced-controls.wasm"
288
286
  build_app "demo/src/routes/templated-controls.ts" "${DEMO_OUT_DIR}/templated-controls.wasm"
289
287
  build_app "demo/src/routes/demo_scrollbar_gutter.ts" "${DEMO_OUT_DIR}/scrollbar-gutter.wasm"
288
+ build_app "demo/src/routes/demo_immediate_drawing.ts" "${DEMO_OUT_DIR}/immediate-drawing.wasm"
290
289
  build_workers
291
- write_worker_manifest
292
290
 
293
291
  npx esbuild "${SMOKE_FIXTURE_DIR}/harness.ts" \
294
292
  --bundle \
@@ -296,6 +294,7 @@ npx esbuild "${SMOKE_FIXTURE_DIR}/harness.ts" \
296
294
  --platform=browser \
297
295
  --target=es2020 \
298
296
  --minify \
297
+ "${ESBUILD_RUNTIME_ALIAS_ARGS[@]}" \
299
298
  --outfile="${OUT_DIR}/harness.js" \
300
299
  --sourcemap
301
300
 
@@ -305,15 +304,17 @@ npx esbuild "${PACKAGE_DIR}/demo/harness.ts" \
305
304
  --platform=browser \
306
305
  --target=es2020 \
307
306
  --minify \
307
+ "${ESBUILD_RUNTIME_ALIAS_ARGS[@]}" \
308
308
  --outfile="${DEMO_OUT_DIR}/harness.js" \
309
309
  --sourcemap
310
310
 
311
- npx esbuild "${BROWSER_SRC_DIR}/file-processing-worker.ts" \
311
+ npx esbuild "${REPO_ROOT}/v2/browser-bridge/src/managed-harness/file-processing-worker.ts" \
312
312
  --bundle \
313
313
  --format=iife \
314
314
  --platform=browser \
315
315
  --target=es2020 \
316
316
  --minify \
317
+ "${ESBUILD_RUNTIME_ALIAS_ARGS[@]}" \
317
318
  --outfile="${FILE_PROCESSING_WORKER_BUILD}" \
318
319
  --sourcemap
319
320
 
@@ -322,12 +323,13 @@ cp "${FILE_PROCESSING_WORKER_MAP_BUILD}" "${OUT_DIR}/file-processing-worker.js.m
322
323
  cp "${FILE_PROCESSING_WORKER_BUILD}" "${DEMO_OUT_DIR}/file-processing-worker.js"
323
324
  cp "${FILE_PROCESSING_WORKER_MAP_BUILD}" "${DEMO_OUT_DIR}/file-processing-worker.js.map"
324
325
 
325
- npx esbuild "${BROWSER_SRC_DIR}/worker-bootstrap.ts" \
326
+ npx esbuild "${REPO_ROOT}/v2/browser-bridge/src/managed-harness/worker-bootstrap.ts" \
326
327
  --bundle \
327
328
  --format=iife \
328
329
  --platform=browser \
329
330
  --target=es2020 \
330
331
  --minify \
332
+ "${ESBUILD_RUNTIME_ALIAS_ARGS[@]}" \
331
333
  --outfile="${WORKER_BOOTSTRAP_BUILD}" \
332
334
  --sourcemap
333
335
 
@@ -346,10 +348,11 @@ cp "${PACKAGE_DIR}/browser/favicon.ico" "${REPO_ROOT}/public/favicon.ico"
346
348
  cp "${PACKAGE_DIR}/demo/demo-texture.png" "${DEMO_OUT_DIR}/demo-texture.png"
347
349
  cp "${PACKAGE_DIR}/demo/demo-secondary-texture.png" "${DEMO_OUT_DIR}/demo-secondary-texture.png"
348
350
 
349
- mkdir -p "${DEMO_OUT_DIR}/advanced-controls" "${DEMO_OUT_DIR}/templated-controls" "${DEMO_OUT_DIR}/scrollbar-gutter"
351
+ mkdir -p "${DEMO_OUT_DIR}/advanced-controls" "${DEMO_OUT_DIR}/templated-controls" "${DEMO_OUT_DIR}/scrollbar-gutter" "${DEMO_OUT_DIR}/immediate-drawing"
350
352
  render_html_with_loading_overlay "${PACKAGE_DIR}/demo/route-shell.html" "${DEMO_OUT_DIR}/advanced-controls/index.html"
351
353
  render_html_with_loading_overlay "${PACKAGE_DIR}/demo/route-shell.html" "${DEMO_OUT_DIR}/templated-controls/index.html"
352
354
  render_html_with_loading_overlay "${PACKAGE_DIR}/demo/route-shell.html" "${DEMO_OUT_DIR}/scrollbar-gutter/index.html"
355
+ render_html_with_loading_overlay "${PACKAGE_DIR}/demo/route-shell.html" "${DEMO_OUT_DIR}/immediate-drawing/index.html"
353
356
 
354
357
  copy_runtime_assets "${OUT_DIR}"
355
358
  copy_runtime_assets "${DEMO_OUT_DIR}"
@@ -360,3 +363,4 @@ write_runtime_config "${DEMO_OUT_DIR}" "${DEFAULT_MANIFEST_PATH}"
360
363
  write_runtime_config "${DEMO_OUT_DIR}/advanced-controls" "../runtime/dist/effindom.v2.manifest.json"
361
364
  write_runtime_config "${DEMO_OUT_DIR}/templated-controls" "../runtime/dist/effindom.v2.manifest.json"
362
365
  write_runtime_config "${DEMO_OUT_DIR}/scrollbar-gutter" "../runtime/dist/effindom.v2.manifest.json"
366
+ write_runtime_config "${DEMO_OUT_DIR}/immediate-drawing" "../runtime/dist/effindom.v2.manifest.json"
@@ -1,4 +1,4 @@
1
- import { defineHostServices, hostService } from "../browser/src/host-services";
1
+ import { defineHostServices, hostService } from "../browser/src/shared-browser";
2
2
 
3
3
  function unsupported(): never {
4
4
  throw new Error("Framework host service definitions are generator metadata only.");