@effindomv2/fui-as 0.1.37 → 0.1.41

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 +3 -0
  6. package/package.json +23 -13
  7. package/scripts/build.sh +70 -46
  8. package/scripts/check-runtime-dependency.sh +0 -19
  9. package/scripts/framework-host-services.ts +1 -1
  10. package/scripts/generate-host-events.ts +15 -241
  11. package/scripts/generate-host-services.ts +13 -261
  12. package/scripts/hostgen/assemblyscript-host-events.ts +165 -0
  13. package/scripts/hostgen/assemblyscript-host-services.ts +207 -0
  14. package/scripts/hostgen/common.ts +73 -0
  15. package/scripts/hostgen/registry.ts +159 -0
  16. package/src/Fui.ts +65 -5
  17. package/src/FuiExports.ts +12 -1
  18. package/src/bindings/ui.ts +157 -8
  19. package/src/controls/Button.ts +98 -71
  20. package/src/controls/Checkbox.ts +23 -21
  21. package/src/controls/ComboBox.ts +1201 -0
  22. package/src/controls/ContextMenu.ts +279 -165
  23. package/src/controls/Dialog.ts +91 -17
  24. package/src/controls/Dropdown.ts +101 -333
  25. package/src/controls/NavLink.ts +29 -6
  26. package/src/controls/Popup.ts +10 -5
  27. package/src/controls/ProgressBar.ts +1 -2
  28. package/src/controls/RadioButton.ts +34 -13
  29. package/src/controls/RadioGroup.ts +32 -19
  30. package/src/controls/Slider.ts +21 -23
  31. package/src/controls/Switch.ts +34 -17
  32. package/src/controls/index.ts +2 -1
  33. package/src/controls/internal/ButtonPresenter.ts +5 -2
  34. package/src/controls/internal/CheckboxIndicatorPresenter.ts +10 -10
  35. package/src/controls/internal/DropdownChevronPresenter.ts +3 -3
  36. package/src/controls/internal/DropdownFieldPresenter.ts +6 -6
  37. package/src/controls/internal/DropdownOptionRowPresenter.ts +5 -4
  38. package/src/controls/internal/PressableLabeledControl.ts +4 -7
  39. package/src/controls/internal/RadioIndicatorPresenter.ts +7 -7
  40. package/src/controls/internal/SelectablePopupList.ts +463 -0
  41. package/src/controls/internal/SliderPresenter.ts +5 -5
  42. package/src/controls/internal/SwitchIndicatorPresenter.ts +63 -17
  43. package/src/controls/internal/TextInputCore.ts +307 -41
  44. package/src/controls/internal/TextInputPresenter.ts +2 -2
  45. package/src/controls/templating.ts +10 -0
  46. package/src/core/Application.ts +17 -8
  47. package/src/core/Bitmap.ts +192 -3
  48. package/src/core/ContextMenuManager.ts +128 -44
  49. package/src/core/DebugApi.ts +17 -2
  50. package/src/core/DragGesture.ts +8 -7
  51. package/src/core/EventRouter.ts +332 -12
  52. package/src/core/Fetch.ts +15 -7
  53. package/src/core/FetchFfi.ts +1 -15
  54. package/src/core/File.ts +75 -34
  55. package/src/core/FocusAdornerManager.ts +3 -3
  56. package/src/core/FocusVisibility.ts +7 -0
  57. package/src/core/FrameScheduler.ts +104 -5
  58. package/src/core/ImageSampling.ts +43 -0
  59. package/src/core/Logger.ts +2 -0
  60. package/src/core/MobileTextSelectionToolbarManager.ts +901 -0
  61. package/src/core/Node.ts +1039 -97
  62. package/src/core/Platform.ts +16 -16
  63. package/src/core/SelectionHandleAdornerManager.ts +697 -0
  64. package/src/core/Theme.ts +34 -20
  65. package/src/core/ToolTipManager.ts +3 -3
  66. package/src/core/Typography.ts +411 -19
  67. package/src/core/Worker.ts +69 -33
  68. package/src/core/event_exports.ts +123 -5
  69. package/src/core/ffi.ts +5 -865
  70. package/src/core/generated/FetchHostAbi.ts +10 -0
  71. package/src/core/generated/FrameworkHostServices.ts +1 -1
  72. package/src/core/generated/HostAbi.ts +220 -0
  73. package/src/core/generated/UiAbi.ts +356 -0
  74. package/src/core/generated/UiEnums.ts +186 -0
  75. package/src/drawing/DrawCallback.ts +17 -1
  76. package/src/drawing/DrawContext.ts +140 -32
  77. package/src/nodes/CustomDrawable.ts +8 -1
  78. package/src/nodes/FlexBox.ts +40 -11
  79. package/src/nodes/Grid.ts +5 -5
  80. package/src/nodes/Image.ts +20 -1
  81. package/src/nodes/RichText.ts +36 -25
  82. package/src/nodes/ScrollBar.ts +2 -1
  83. package/src/nodes/ScrollBox.ts +7 -2
  84. package/src/nodes/ScrollView.ts +17 -6
  85. package/src/nodes/Svg.ts +18 -1
  86. package/src/nodes/Text.ts +1 -1
  87. package/src/nodes/TextCore.ts +115 -20
  88. package/src/nodes/index.ts +1 -1
  89. package/src/text/DynamicTextLayout.ts +275 -0
  90. package/src/text/TextLayout.ts +308 -0
  91. package/src/worker/Worker.ts +3 -36
  92. package/src/worker/WorkerJob.ts +5 -9
  93. package/src/worker/ffi.ts +0 -6
  94. package/browser/src/common-harness/host-imports.ts +0 -447
  95. package/browser/src/common-harness/interop.ts +0 -39
  96. package/browser/src/common-harness/managed-harness-bitmap-host.ts +0 -92
  97. package/browser/src/common-harness/managed-harness-canvas-host.ts +0 -72
  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 -1472
  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 -206
  109. package/browser/src/common-harness/ui-chrome.ts +0 -206
  110. package/browser/src/common-harness/ui-imports.ts +0 -559
  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 '@effindomv2/runtime/routed-app-conventions';
@@ -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,3 @@
1
+ export * from '@effindomv2/runtime/managed-harness';
2
+ export * from '@effindomv2/runtime/routed-app-conventions';
3
+ export * from '@effindomv2/runtime/routed-harness';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@effindomv2/fui-as",
3
- "version": "0.1.37",
3
+ "version": "0.1.41",
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,22 +80,28 @@
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
98
  "@assemblyscript/loader": "^0.28.19",
89
- "@effindomv2/runtime": "0.1.18"
99
+ "@effindomv2/runtime": "0.1.22"
90
100
  },
91
101
  "devDependencies": {
92
- "@as-pect/assembly": "8.1.0",
93
- "@as-pect/cli": "8.1.0",
94
- "@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",
95
105
  "@playwright/test": "1.59.1",
96
106
  "@types/node": "^24.10.1",
97
107
  "assemblyscript": "0.28.19",
package/scripts/build.sh CHANGED
@@ -13,15 +13,20 @@ 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"
24
24
  LOADING_OVERLAY_BODY_FILE="${PACKAGE_DIR}/browser/loading-overlay-body.html"
25
+ RUNTIME_PACKAGE_DIR="${PACKAGE_DIR}/node_modules/@effindomv2/runtime"
26
+
27
+ if [ ! -d "${RUNTIME_PACKAGE_DIR}" ]; then
28
+ RUNTIME_PACKAGE_DIR="${REPO_ROOT}/node_modules/@effindomv2/runtime"
29
+ fi
25
30
 
26
31
  rm -rf "${OUT_DIR}"
27
32
  mkdir -p "${PACKAGE_DIR}/build" "${OUT_DIR}" "${DEMO_OUT_DIR}" "${WORKER_BUILD_DIR}"
@@ -37,6 +42,48 @@ else
37
42
  exit 1
38
43
  fi
39
44
 
45
+ ESBUILD_RUNTIME_ALIAS_ARGS=()
46
+ LOCAL_RUNTIME_PACKAGE_JSON="${REPO_ROOT}/v2/browser-bridge/package.json"
47
+ if [ -f "${LOCAL_RUNTIME_PACKAGE_JSON}" ]; then
48
+ REQUIRED_RUNTIME_VERSION="$(
49
+ node -e '
50
+ const pkg = require(process.argv[1]);
51
+ process.stdout.write(String(pkg.dependencies?.["@effindomv2/runtime"] ?? ""));
52
+ ' "${PACKAGE_DIR}/package.json"
53
+ )"
54
+ LOCAL_RUNTIME_VERSION="$(
55
+ node -e '
56
+ const pkg = require(process.argv[1]);
57
+ process.stdout.write(String(pkg.version ?? ""));
58
+ ' "${LOCAL_RUNTIME_PACKAGE_JSON}"
59
+ )"
60
+ else
61
+ REQUIRED_RUNTIME_VERSION=""
62
+ LOCAL_RUNTIME_VERSION=""
63
+ fi
64
+
65
+ if [ -n "${REQUIRED_RUNTIME_VERSION}" ] && [ "${LOCAL_RUNTIME_VERSION}" = "${REQUIRED_RUNTIME_VERSION}" ]; then
66
+ ESBUILD_RUNTIME_ALIAS_ARGS+=(
67
+ "--alias:@effindomv2/runtime=${REPO_ROOT}/v2/browser-bridge/src"
68
+ )
69
+ fi
70
+
71
+ generate_abi() {
72
+ npx esbuild "${REPO_ROOT}/v2/abi/generate.ts" \
73
+ --bundle \
74
+ --format=esm \
75
+ --platform=node \
76
+ --target=node20 \
77
+ --packages=external \
78
+ --outfile="${ABI_GENERATOR_BUILD}"
79
+
80
+ node "${ABI_GENERATOR_BUILD}" fui-as-ui
81
+ node "${ABI_GENERATOR_BUILD}" fui-as-host
82
+ node "${ABI_GENERATOR_BUILD}" fui-as-enums
83
+ }
84
+
85
+ generate_abi
86
+
40
87
  "${TSC_BIN}" -p tsconfig.json --noEmit
41
88
 
42
89
  build_app() {
@@ -119,6 +166,10 @@ find_worker_entries() {
119
166
 
120
167
  resolve_runtime_dist_dir() {
121
168
  local candidate=""
169
+ local public_runtime_dir="${REPO_ROOT}/public/v2/browser-bridge"
170
+ local package_runtime_dir="${REPO_ROOT}/v2/browser-bridge/dist"
171
+ local public_manifest="${public_runtime_dir}/effindom.v2.manifest.json"
172
+ local package_manifest="${package_runtime_dir}/effindom.v2.manifest.json"
122
173
  local candidates=()
123
174
 
124
175
  if [ -n "${EFFINDOM_RUNTIME_DIST_DIR:-}" ]; then
@@ -126,12 +177,18 @@ resolve_runtime_dist_dir() {
126
177
  fi
127
178
 
128
179
  candidates+=(
129
- "${REPO_ROOT}/public/v2/browser-bridge"
130
- "${REPO_ROOT}/v2/browser-bridge/dist"
180
+ "${public_runtime_dir}"
181
+ "${package_runtime_dir}"
131
182
  "${PACKAGE_DIR}/node_modules/@effindomv2/runtime/dist"
132
183
  "${REPO_ROOT}/node_modules/@effindomv2/runtime/dist"
133
184
  )
134
185
 
186
+ if [ -f "${public_manifest}" ] && [ -f "${package_manifest}" ] && ! cmp -s "${public_manifest}" "${package_manifest}"; then
187
+ echo "Note: using ${public_runtime_dir} for monorepo runtime assets." >&2
188
+ echo " ${package_runtime_dir} is a staged package copy and may be stale." >&2
189
+ echo " For ABI changes, run repo-root ./build.sh (or npm run build:v2:abi)." >&2
190
+ fi
191
+
135
192
  for candidate in "${candidates[@]}"; do
136
193
  if [ -f "${candidate}/bridge.js" ] && [ -f "${candidate}/effindom.v2.manifest.json" ] && [ -d "${candidate}/runtime" ]; then
137
194
  printf '%s\n' "${candidate}"
@@ -144,8 +201,9 @@ resolve_runtime_dist_dir() {
144
201
  echo " - \$EFFINDOM_RUNTIME_DIST_DIR" >&2
145
202
  echo " - ${PACKAGE_DIR}/node_modules/@effindomv2/runtime/dist" >&2
146
203
  echo " - ${REPO_ROOT}/node_modules/@effindomv2/runtime/dist" >&2
147
- echo " - ${REPO_ROOT}/v2/browser-bridge/dist" >&2
148
204
  echo " - ${REPO_ROOT}/public/v2/browser-bridge" >&2
205
+ echo " - ${REPO_ROOT}/v2/browser-bridge/dist" >&2
206
+ echo "Monorepo note: repo-root ./build.sh (or npm run build:v2:abi) refreshes the runtime assets used here." >&2
149
207
  echo "Install @effindomv2/runtime or build runtime assets first." >&2
150
208
  exit 1
151
209
  }
@@ -158,7 +216,8 @@ write_runtime_config() {
158
216
 
159
217
  cat > "${destination}/${RUNTIME_CONFIG_FILE}" <<EOF
160
218
  window.__effindomRuntime = Object.assign({}, window.__effindomRuntime, {
161
- manifestUrl: '${manifest_url}',
219
+ manifestUrl: new URL('${manifest_url}', document.currentScript && document.currentScript.src ? document.currentScript.src : document.baseURI).toString(),
220
+ buildMode: 'debug',
162
221
  });
163
222
  EOF
164
223
  }
@@ -222,43 +281,6 @@ build_workers() {
222
281
  done < <(find_worker_entries)
223
282
  }
224
283
 
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
284
  copy_worker_assets() {
263
285
  local destination="$1"
264
286
  rm -rf "${destination}/workers"
@@ -273,7 +295,6 @@ copy_worker_assets() {
273
295
  cp "${WORKER_BOOTSTRAP_MAP_BUILD}" "${destination}/worker-bootstrap.js.map"
274
296
  cp "${WORKER_HOST_SERVICES_BUILD}" "${destination}/worker-host-services.js"
275
297
  cp "${WORKER_HOST_SERVICES_MAP_BUILD}" "${destination}/worker-host-services.js.map"
276
- cp "${WORKER_MANIFEST_BUILD}" "${destination}/worker-manifest.json"
277
298
  }
278
299
 
279
300
  generate_host_services "demo/src/host-services.ts" "demoHostServices" "demo/src/generated/HostServices.ts"
@@ -289,7 +310,6 @@ build_app "demo/src/routes/templated-controls.ts" "${DEMO_OUT_DIR}/templated-con
289
310
  build_app "demo/src/routes/demo_scrollbar_gutter.ts" "${DEMO_OUT_DIR}/scrollbar-gutter.wasm"
290
311
  build_app "demo/src/routes/demo_immediate_drawing.ts" "${DEMO_OUT_DIR}/immediate-drawing.wasm"
291
312
  build_workers
292
- write_worker_manifest
293
313
 
294
314
  npx esbuild "${SMOKE_FIXTURE_DIR}/harness.ts" \
295
315
  --bundle \
@@ -297,6 +317,7 @@ npx esbuild "${SMOKE_FIXTURE_DIR}/harness.ts" \
297
317
  --platform=browser \
298
318
  --target=es2020 \
299
319
  --minify \
320
+ "${ESBUILD_RUNTIME_ALIAS_ARGS[@]}" \
300
321
  --outfile="${OUT_DIR}/harness.js" \
301
322
  --sourcemap
302
323
 
@@ -306,15 +327,17 @@ npx esbuild "${PACKAGE_DIR}/demo/harness.ts" \
306
327
  --platform=browser \
307
328
  --target=es2020 \
308
329
  --minify \
330
+ "${ESBUILD_RUNTIME_ALIAS_ARGS[@]}" \
309
331
  --outfile="${DEMO_OUT_DIR}/harness.js" \
310
332
  --sourcemap
311
333
 
312
- npx esbuild "${BROWSER_SRC_DIR}/file-processing-worker.ts" \
334
+ npx esbuild "${RUNTIME_PACKAGE_DIR}/src/managed-harness/file-processing-worker.ts" \
313
335
  --bundle \
314
336
  --format=iife \
315
337
  --platform=browser \
316
338
  --target=es2020 \
317
339
  --minify \
340
+ "${ESBUILD_RUNTIME_ALIAS_ARGS[@]}" \
318
341
  --outfile="${FILE_PROCESSING_WORKER_BUILD}" \
319
342
  --sourcemap
320
343
 
@@ -323,12 +346,13 @@ cp "${FILE_PROCESSING_WORKER_MAP_BUILD}" "${OUT_DIR}/file-processing-worker.js.m
323
346
  cp "${FILE_PROCESSING_WORKER_BUILD}" "${DEMO_OUT_DIR}/file-processing-worker.js"
324
347
  cp "${FILE_PROCESSING_WORKER_MAP_BUILD}" "${DEMO_OUT_DIR}/file-processing-worker.js.map"
325
348
 
326
- npx esbuild "${BROWSER_SRC_DIR}/worker-bootstrap.ts" \
349
+ npx esbuild "${RUNTIME_PACKAGE_DIR}/src/managed-harness/worker-bootstrap.ts" \
327
350
  --bundle \
328
351
  --format=iife \
329
352
  --platform=browser \
330
353
  --target=es2020 \
331
354
  --minify \
355
+ "${ESBUILD_RUNTIME_ALIAS_ARGS[@]}" \
332
356
  --outfile="${WORKER_BOOTSTRAP_BUILD}" \
333
357
  --sourcemap
334
358
 
@@ -3,9 +3,7 @@
3
3
  set -euo pipefail
4
4
 
5
5
  PACKAGE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
6
- REPO_ROOT="$(cd "${PACKAGE_DIR}/../.." && pwd)"
7
6
  PACKAGE_JSON="${PACKAGE_DIR}/package.json"
8
- RUNTIME_PACKAGE_JSON="${REPO_ROOT}/v2/browser-bridge/package.json"
9
7
 
10
8
  if [ ! -f "${PACKAGE_JSON}" ]; then
11
9
  echo "Missing package.json at ${PACKAGE_JSON}" >&2
@@ -29,20 +27,3 @@ if ! printf '%s' "${runtime_spec}" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+([-.][0-9A
29
27
  echo "@effindomv2/runtime must be pinned to an exact version, found: ${runtime_spec}" >&2
30
28
  exit 1
31
29
  fi
32
-
33
- if [ -f "${RUNTIME_PACKAGE_JSON}" ]; then
34
- runtime_version="$(
35
- node -e '
36
- const fs = require("node:fs");
37
- const pkg = JSON.parse(fs.readFileSync(process.argv[1], "utf8"));
38
- process.stdout.write(String(pkg.version ?? ""));
39
- ' "${RUNTIME_PACKAGE_JSON}"
40
- )"
41
-
42
- if [ -n "${runtime_version}" ] && [ "${runtime_spec}" != "${runtime_version}" ]; then
43
- echo "@effindomv2/fui-as depends on @effindomv2/runtime@${runtime_spec}, but monorepo runtime is ${runtime_version}." >&2
44
- echo "Update v2/fui-as/package.json to match v2/browser-bridge/package.json." >&2
45
- exit 1
46
- fi
47
- fi
48
-
@@ -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.");